Java对象Avro的Json字符串

Java对象Avro的Json字符串,java,json,avro,Java,Json,Avro,我正在尝试将Json字符串转换为具有Avro模式的通用Java对象 下面是我的代码 String json = "{\"foo\": 30.1, \"bar\": 60.2}"; String schemaLines = "{\"type\":\"record\",\"name\":\"FooBar\",\"namespace\":\"com.foo.bar\",\"fields\":[{\"name\":\"foo\",\"type\":[\"null\",\"double\"],\"defa

我正在尝试将Json字符串转换为具有Avro模式的通用Java对象

下面是我的代码

String json = "{\"foo\": 30.1, \"bar\": 60.2}";
String schemaLines = "{\"type\":\"record\",\"name\":\"FooBar\",\"namespace\":\"com.foo.bar\",\"fields\":[{\"name\":\"foo\",\"type\":[\"null\",\"double\"],\"default\":null},{\"name\":\"bar\",\"type\":[\"null\",\"double\"],\"default\":null}]}";

InputStream input = new ByteArrayInputStream(json.getBytes());
DataInputStream din = new DataInputStream(input);

Schema schema = Schema.parse(schemaLines);

Decoder decoder = DecoderFactory.get().jsonDecoder(schema, din);

DatumReader<Object> reader = new GenericDatumReader<Object>(schema);
Object datum = reader.read(null, decoder);
String json=“{\'foo\':30.1,\'bar\':60.2}”;
字符串模式=“{\'type\':\'record\',\'name\':\'FooBar\',\'namespace\':\'com.foo.bar\',\'fields\':[{\'name\':\'foo\',\'type\':[\'null\',\'double\'],\'default\':null},{\'name\':'bar\',\'type\'type\':[\'null\','double\','default;
InputStream input=new ByteArrayInputStream(json.getBytes());
DataInputStream din=新的DataInputStream(输入);
Schema=Schema.parse(schemaLines);
Decoder Decoder=DecoderFactory.get().jsonDecoder(模式,din);
DatumReader=新的GenericDatumReader(模式);
对象数据=reader.read(空,解码器);
我得到了“org.apache.avro.AvroTypeException:Expected start union.get VALUE\u NUMBER\u FLOAT”异常

如果模式中没有联合,那么同样的代码也可以工作。
有人能解释一下并给我一个解决方案吗。

您的模式与json字符串的模式不匹配。您需要有一个不同的模式,该模式在错误处没有并集,而是有一个十进制数。这样的模式应该被用作writer模式,而您可以自由地使用另一个作为reader模式。

多亏了Reza。我找到了这个网页。 它介绍了如何将Json字符串转换为avro对象

他的代码的关键是:

static byte[] fromJsonToAvro(String json, String schemastr) throws Exception {
  InputStream input = new ByteArrayInputStream(json.getBytes());
  DataInputStream din = new DataInputStream(input);

  Schema schema = Schema.parse(schemastr);

  Decoder decoder = DecoderFactory.get().jsonDecoder(schema, din);

  DatumReader<Object> reader = new GenericDatumReader<Object>(schema);
  Object datum = reader.read(null, decoder);

  GenericDatumWriter<Object>  w = new GenericDatumWriter<Object>(schema);
  ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

  Encoder e = EncoderFactory.get().binaryEncoder(outputStream, null);

  w.write(datum, e);
  e.flush();

  return outputStream.toByteArray();
}

String json = "{\"username\":\"miguno\",\"tweet\":\"Rock: Nerf paper, scissors is fine.\",\"timestamp\": 1366150681 }";

String schemastr ="{ \"type\" : \"record\", \"name\" : \"twitter_schema\", \"namespace\" : \"com.miguno.avro\", \"fields\" : [ { \"name\" : \"username\", \"type\" : \"string\", \"doc\"  : \"Name of the user account on Twitter.com\" }, { \"name\" : \"tweet\", \"type\" : \"string\", \"doc\"  : \"The content of the user's Twitter message\" }, { \"name\" : \"timestamp\", \"type\" : \"long\", \"doc\"  : \"Unix epoch time in seconds\" } ], \"doc:\" : \"A basic schema for storing Twitter messages\" }";

byte[] avroByteArray = fromJsonToAvro(json,schemastr);

Schema schema = Schema.parse(schemastr);
DatumReader<Genericrecord> reader1 = new GenericDatumReader<Genericrecord>(schema);

Decoder decoder1 = DecoderFactory.get().binaryDecoder(avroByteArray, null);
GenericRecord result = reader1.read(null, decoder1);
JSONTAVRO(字符串json,字符串Schematr)的静态字节[]引发异常{ InputStream input=new ByteArrayInputStream(json.getBytes()); DataInputStream din=新的DataInputStream(输入); Schema=Schema.parse(schemastr); Decoder Decoder=DecoderFactory.get().jsonDecoder(模式,din); DatumReader=新的GenericDatumReader(模式); 对象数据=reader.read(空,解码器); GenericDatumWriter w=新的GenericDatumWriter(模式); ByteArrayOutputStream outputStream=新建ByteArrayOutputStream(); 编码器e=EncoderFactory.get().binaryEncoder(outputStream,null); w、 写入(数据,e); e、 冲洗(); 返回outputStream.toByteArray(); } 字符串json=“{\'username\':\'miguno\',\'tweet\':\'Rock:Nerf纸,剪刀很好。\',\'timestamp\':1366150681}”; String schemastr=“{\'type\”:\“record\”,\“name\”:“twitter\u schema\”,\“namespace\”:“com.miguno.avro\”,\“fields\”:[{\'name\”:“username\”,“type\”:“String\”,“doc\”:“twitter.com上的用户帐户名\”,{\'name\:“tweet\”,“type\”:“type\:“String\”,“doc\”:“用户twitter消息的内容”,{名称\“:\“timestamp\”,\“type\”:“long\”,\“doc\”:“Unix纪元时间(秒)”,\“doc:\”:“存储Twitter消息的基本模式\“}”; 字节[]avroByteArray=fromJSONTAVRO(json,schematr); Schema=Schema.parse(schemastr); DatumReader reader1=新的GenericDatumReader(模式); Decoder decoder1=DecoderFactory.get().binaryDecoder(avroByteArray,null); GenericRecord结果=reader1.read(null,decoder1);
使用Avro 1.4.1,它可以:

private static GenericData.Record parseJson(String json, String schema)
    throws IOException {
  Schema parsedSchema = Schema.parse(schema);
  Decoder decoder = new JsonDecoder(parsedSchema, json);

  DatumReader<GenericData.Record> reader =
      new GenericDatumReader<>(parsedSchema);
  return reader.read(null, decoder);
}
private static GenericData.Record parseJson(字符串json,字符串模式)
抛出IOException{
Schema parsedSchema=Schema.parse(Schema);
解码器=新的JsonDecoder(parsedSchema,json);
数据读取器=
新的GenericDatumReader(parsedSchema);
返回reader.read(null,解码器);
}

可能需要对以后的Avro版本进行一些调整。

对于任何使用Avro-1.8.2的人来说,
JsonDecoder
现在不能直接在包
org.apache.Avro.io
之外实例化。您可以对其使用
DecoderFactory
,如下代码所示:

String schemaStr = "<some json schema>";
String genericRecordStr = "<some json record>";
Schema.Parser schemaParser = new Schema.Parser();
Schema schema = schemaParser.parse(schemaStr);
DecoderFactory decoderFactory = new DecoderFactory();
Decoder decoder = decoderFactory.jsonDecoder(schema, genericRecordStr);
DatumReader<GenericData.Record> reader =
            new GenericDatumReader<>(schema);
GenericRecord genericRecord = reader.read(null, decoder);
String schematr=“”;
字符串genericRecordStr=“”;
Schema.Parser schemaParser=新Schema.Parser();
Schema=schemaParser.parse(schemaStr);
DecoderFactory DecoderFactory=新的DecoderFactory();
Decoder-Decoder=decoderFactory.jsonDecoder(模式,genericRecordStr);
数据读取器=
新的GenericDatumReader(模式);
GenericRecord GenericRecord=reader.read(空,解码器);

问题不在于代码,而在于json的错误格式


字符串json=“{”foo:{”double:30.1}”,bar:{“double:60.2}”

正如评论中已经提到的,AVRO libs理解的JSON与普通JSON对象有点不同。具体来说,
UNION
type被包装到一个嵌套的对象结构中:
“UNION\u字段”:{“type”:“value”}

所以,如果您想将“普通”JSON转换为AVRO,您必须使用第三方库。至少现在是这样

  • -
    Java
    声称支持联合的项目,不确定默认值
  • -这是我的项目,虽然是用
    Scala
    编写的,但仍然可以从
    Java
    使用。支持联合、默认值、base64二进制数据

From,我理解联合的Json编码是不同的,但我正在尝试找出是否有任何方法可以将Json字符串转换为object.FYI,
jsonDecoder()的重载接受Json字符串;无需将其转换为流。或者,告诉Avro您正在使用哪一个流,如下所示:
String json=“{\'foo\':{\'double\':30.1},\'bar\':{\'double\':60.2}”这将是avro使用给定模式序列化记录的方式。谢谢Miljanm和Keegan。是的,我知道工会的json编码不同于avro.apache.org/docs/1.7.6/spec.html#json_编码。但我正在寻找一个开源库,它可以在内部将我的json字符串更改为avro特定的模式,然后解析它。有这样的工具吗?我不知道有这样的工具。为什么不想创建一个不同的模式?这个问题的解决方案似乎简单得多,模式与当前模式兼容。这段代码无法解决问题。当架构包含联合时,这不起作用。当我的架构包含联合时,有什么解决方案吗?我得到了
Exce