2014-12-19 3 views
7

Json 문자열을 Avro 스키마가있는 일반 Java 객체로 변환하려고합니다.Json String to Java Object Avro

아래 코드는 제 코드입니다. "예상 시작 노조있어 VALUE_NUMBER_FLOAT org.apache.avro.AvroTypeException을."예외를

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); 

내가 얻을.

스키마에 공용체가 없으면 동일한 코드가 작동합니다. 누군가 설명하고 해결책을 줄 수 있습니까?

+0

http://avro.apache.org/docs/1.7.6/spec.html#json_encoding에서 알기로, Json 인코딩 조합이 다르다는 것을 알고 있지만 어떤 방법이 있는지 알아 내려고합니다. json 문자열을 객체로 변환 할 수 있습니다. –

+1

FYI,'jsonDecoder()'의 오버로드는 json String을 받아 들인다; 스트림으로 변환 할 필요가 없습니다. – jaco0646

답변

0

귀하의 스키마가 json 문자열의 스키마와 일치하지 않습니다. 오류가 아닌 10 진수가 아닌 다른 스키마가 있어야합니다. 이러한 스키마는 라이터 스키마로 사용되어야하며 다른 스키마는 독자적으로 독자 스키마로 사용할 수 있습니다.

+0

Avro에게 사용중인 코드를 알려주십시오. 'String json = "{\"foo \ ": {\"double \ ": 30.1}, \"bar \ ": {\"double \ " : 60.2}} "; ' – Keegan

+0

이것은 avro가 주어진 스키마로 레코드를 직렬화하는 방법입니다. – miljanm

+0

Miljanm과 Keegan에게 감사드립니다. 예, 저는 json 인코딩 조합이 avro.apache.org/docs/1.7.6/spec.html#json_encoding과 다릅니다. 하지만 오픈 소스 라이브러리를 찾고 있는데, 내부적으로 내 json 문자열을 avro 특정 스키마로 변경 한 다음 구문 분석 할 수 있습니다. 그게 뭔가 있는거야? –

6

Reza에게 감사드립니다. 나는이 웹 페이지를 발견했다. Json 문자열을 avro 객체로 변환하는 방법을 소개합니다.

http://rezarahim.blogspot.com/2013/06/import-org_26.html

자신의 코드의 키는 다음과 같습니다

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); 
+0

이 코드는 문제를 해결하지 못합니다. 스키마에 공용체가 포함되어 있으면이 작업이 작동하지 않습니다. – deepak

3

브로 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); 
} 

나중에 브로 버전에 대한 일부 개조하면 되겠 어해야 할 수도 있습니다.