2014-02-24 2 views
3

내 JSON 문자열을 바이너리 인코딩하려고합니다. 아래는 JSON 문자열이며 변환을 수행하는 간단한 방법을 만들었지 만 내가하고있는 방식이 올바른지 아닌지 확실하지 않습니다. 아 브로 진 내 JSON 문자열 인코딩 변환합니다 방법 아래Avro를 사용하는 방법 Apache Avro를 사용하여 JSON 문자열을 바이너리 인코딩 하시겠습니까?

public static void main(String args[]) throws Exception{ 
try{ 
    Schema schema = new Parser().parse((TestExample.class.getResourceAsStream("/3233.avsc"))); 
    String json="{"+ 
     " \"location\" : {"+ 
     " \"devices\":["+ 
     "  {"+ 
     "  \"did\":\"9abd09-439bcd-629a8f\","+ 
     "  \"dt\":\"browser\","+ 
     "  \"usl\":{"+ 
     "   \"pos\":{"+ 
     "   \"source\":\"GPS\","+ 
     "   \"lat\":90.0,"+ 
     "   \"long\":101.0,"+ 
     "   \"acc\":100"+ 
     "   },"+ 
     "   \"addSource\":\"LL\","+ 
     "   \"add\":["+ 
     "   {"+ 
     "    \"val\":\"2123\","+ 
     "    \"type\" : \"NUM\""+ 
     "   },"+ 
     "   {"+ 
     "    \"val\":\"Harris ST\","+ 
     "    \"type\" : \"ST\""+ 
     "   }"+ 
     "   ],"+ 
     "   \"ei\":{"+ 
     "   \"ibm\":true,"+ 
     "   \"sr\":10,"+ 
     "   \"ienz\":true,"+ 
     "   \"enz\":100,"+ 
     "   \"enr\":10"+ 
     "   },"+ 
     "   \"lm\":1390598086120"+ 
     "  }"+ 
     "  }"+ 
     " ],"+ 
     " \"ver\" : \"1.0\""+ 
     " }"+ 
     "}"; 

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

} catch (Exception ex) { 
    // log an exception 
} 

-

private static byte[] fromJsonToAvro(String json, Schema schema) throws Exception { 

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

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

사람이 살펴보고 제가 브로 진에 노력하고 길을 내 JSON 문자열이 정확한지 여부를 알려하거나 아니?

+0

의 [아파치 아 브로 사양 ] (http://avro.apache.org/docs/1.7.6/spec.html). –

+0

Avro 표기법이 JSON 문자열의 형식에 대한 제약 조건의 특정 사양이기 때문에 "Avro"에 대한 JSON 변환이 무엇을 의미하는지 분명하지 않습니다. –

+0

어쨌든, 아파치는 [유틸리티 세트] (http : //avro.apache.org/docs/current/api/java/index.html), 왜 자신 만의 글을 써야하는지 명확하지 않다. –

답변

14

OP가 정확하다고 생각합니다. 이것이 Avro 데이터 파일 인 경우 존재할 스키마가없는 Avro 레코드 자체를 작성합니다. 당신이 파일로 작업하는 경우 다음

는 브로 자체 (유용 내에서 몇 가지 예를의 JSON에서 브로에
        • :. DataFileWriteTool
        • 브로에서 JSON에 : DataFileReadTool

양방향으로가는 완전한 예가 여기에 있습니다.

@Grapes([ 
    @Grab(group='org.apache.avro', module='avro', version='1.7.7') 
]) 

import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.DataInputStream; 
import java.io.EOFException; 
import java.io.IOException; 
import java.io.InputStream; 

import org.apache.avro.Schema; 
import org.apache.avro.generic.GenericDatumReader; 
import org.apache.avro.generic.GenericDatumWriter; 
import org.apache.avro.generic.GenericRecord; 
import org.apache.avro.io.DatumReader; 
import org.apache.avro.io.DatumWriter; 
import org.apache.avro.io.Decoder; 
import org.apache.avro.io.DecoderFactory; 
import org.apache.avro.io.Encoder; 
import org.apache.avro.io.EncoderFactory; 
import org.apache.avro.io.JsonEncoder; 

String schema = '''{ 
    "type":"record", 
    "namespace":"foo", 
    "name":"Person", 
    "fields":[ 
    { 
     "name":"name", 
     "type":"string" 
    }, 
    { 
     "name":"age", 
     "type":"int" 
    } 
    ] 
}''' 
String json = "{" + 
    "\"name\":\"Frank\"," + 
    "\"age\":47" + 
"}" 

assert avroToJson(jsonToAvro(json, schema), schema) == json 


public static byte[] jsonToAvro(String json, String schemaStr) throws IOException { 
    InputStream input = null; 
    GenericDatumWriter<GenericRecord> writer = null; 
    Encoder encoder = null; 
    ByteArrayOutputStream output = null; 
    try { 
     Schema schema = new Schema.Parser().parse(schemaStr); 
     DatumReader<GenericRecord> reader = new GenericDatumReader<GenericRecord>(schema); 
     input = new ByteArrayInputStream(json.getBytes()); 
     output = new ByteArrayOutputStream(); 
     DataInputStream din = new DataInputStream(input); 
     writer = new GenericDatumWriter<GenericRecord>(schema); 
     Decoder decoder = DecoderFactory.get().jsonDecoder(schema, din); 
     encoder = EncoderFactory.get().binaryEncoder(output, null); 
     GenericRecord datum; 
     while (true) { 
      try { 
       datum = reader.read(null, decoder); 
      } catch (EOFException eofe) { 
       break; 
      } 
      writer.write(datum, encoder); 
     } 
     encoder.flush(); 
     return output.toByteArray(); 
    } finally { 
     try { input.close(); } catch (Exception e) { } 
    } 
} 

public static String avroToJson(byte[] avro, String schemaStr) throws IOException { 
    boolean pretty = false; 
    GenericDatumReader<GenericRecord> reader = null; 
    JsonEncoder encoder = null; 
    ByteArrayOutputStream output = null; 
    try { 
     Schema schema = new Schema.Parser().parse(schemaStr); 
     reader = new GenericDatumReader<GenericRecord>(schema); 
     InputStream input = new ByteArrayInputStream(avro); 
     output = new ByteArrayOutputStream(); 
     DatumWriter<GenericRecord> writer = new GenericDatumWriter<GenericRecord>(schema); 
     encoder = EncoderFactory.get().jsonEncoder(schema, output, pretty); 
     Decoder decoder = DecoderFactory.get().binaryDecoder(input, null); 
     GenericRecord datum; 
     while (true) { 
      try { 
       datum = reader.read(null, decoder); 
      } catch (EOFException eofe) { 
       break; 
      } 
      writer.write(datum, encoder); 
     } 
     encoder.flush(); 
     output.flush(); 
     return new String(output.toByteArray()); 
    } finally { 
     try { if (output != null) output.close(); } catch (Exception e) { } 
    } 
} 

레코드가 아닌 스트림 (Avro는 container files)으로 작업하는 경우를 예로 들겠습니다. JSON에서 Avro로 돌아 가면 스키마를 전달할 필요가 없습니다. 이는 스트림에 존재하기 때문입니다.

@Grapes([ 
    @Grab(group='org.apache.avro', module='avro', version='1.7.7') 
]) 

// writes Avro as a http://avro.apache.org/docs/current/spec.html#Object+Container+Files rather than a sequence of records 

import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.DataInputStream; 
import java.io.EOFException; 
import java.io.IOException; 
import java.io.InputStream; 

import org.apache.avro.Schema; 
import org.apache.avro.file.DataFileStream; 
import org.apache.avro.file.DataFileWriter; 
import org.apache.avro.generic.GenericDatumReader; 
import org.apache.avro.generic.GenericDatumWriter; 
import org.apache.avro.generic.GenericRecord; 
import org.apache.avro.io.DatumReader; 
import org.apache.avro.io.DatumWriter; 
import org.apache.avro.io.Decoder; 
import org.apache.avro.io.DecoderFactory; 
import org.apache.avro.io.Encoder; 
import org.apache.avro.io.EncoderFactory; 
import org.apache.avro.io.JsonEncoder; 


String schema = '''{ 
    "type":"record", 
    "namespace":"foo", 
    "name":"Person", 
    "fields":[ 
    { 
     "name":"name", 
     "type":"string" 
    }, 
    { 
     "name":"age", 
     "type":"int" 
    } 
    ] 
}''' 
String json = "{" + 
    "\"name\":\"Frank\"," + 
    "\"age\":47" + 
"}" 

assert avroToJson(jsonToAvro(json, schema)) == json 


public static byte[] jsonToAvro(String json, String schemaStr) throws IOException { 
    InputStream input = null; 
    DataFileWriter<GenericRecord> writer = null; 
    Encoder encoder = null; 
    ByteArrayOutputStream output = null; 
    try { 
     Schema schema = new Schema.Parser().parse(schemaStr); 
     DatumReader<GenericRecord> reader = new GenericDatumReader<GenericRecord>(schema); 
     input = new ByteArrayInputStream(json.getBytes()); 
     output = new ByteArrayOutputStream(); 
     DataInputStream din = new DataInputStream(input); 
     writer = new DataFileWriter<GenericRecord>(new GenericDatumWriter<GenericRecord>()); 
     writer.create(schema, output); 
     Decoder decoder = DecoderFactory.get().jsonDecoder(schema, din); 
     GenericRecord datum; 
     while (true) { 
      try { 
       datum = reader.read(null, decoder); 
      } catch (EOFException eofe) { 
       break; 
      } 
      writer.append(datum); 
     } 
     writer.flush(); 
     return output.toByteArray(); 
    } finally { 
     try { input.close(); } catch (Exception e) { } 
    } 
} 

public static String avroToJson(byte[] avro) throws IOException { 
    boolean pretty = false; 
    GenericDatumReader<GenericRecord> reader = null; 
    JsonEncoder encoder = null; 
    ByteArrayOutputStream output = null; 
    try { 
     reader = new GenericDatumReader<GenericRecord>(); 
     InputStream input = new ByteArrayInputStream(avro); 
     DataFileStream<GenericRecord> streamReader = new DataFileStream<GenericRecord>(input, reader); 
     output = new ByteArrayOutputStream(); 
     Schema schema = streamReader.getSchema(); 
     DatumWriter<GenericRecord> writer = new GenericDatumWriter<GenericRecord>(schema); 
     encoder = EncoderFactory.get().jsonEncoder(schema, output, pretty); 
     for (GenericRecord datum : streamReader) { 
      writer.write(datum, encoder); 
     } 
     encoder.flush(); 
     output.flush(); 
     return new String(output.toByteArray()); 
    } finally { 
     try { if (output != null) output.close(); } catch (Exception e) { } 
    } 
} 
1

키건의 대답에 추가하려면 ,이 논의는 가능성이 유용

http://mail-archives.apache.org/mod_mbox/avro-user/201209.mbox/%[email protected].com%3E

요점이 특별한 JSON 스키마이며과에서 얻을 JsonReader/라이터를 사용할 수 있다는 것입니다 그. 사용해야하는 JSON 스키마 정의된다 : 당신이 JSON 파일의 스키마 ({schema_file}.avsc을) 알고

https://github.com/apache/avro/blob/trunk/share/schemas/org/apache/avro/data/Json.avsc

0

당신은 브로 파일로 JSON 파일 ({input_file}.json) ({output_file}.avro를) 변환 할 avro-tools을 사용할 수 있습니다 . 다만 아래와 같이 : 그런데

java -jar the/path/of/avro-tools-1.8.1.jar fromjson {input_file}.json --schema-file {schema_file}.avsc > {output_file}.avro 

, {schema_file}.avsc 파일의 내용은 belows과 같습니다

{"type": "record", 
"name": "User", 
    "fields": [ 
     {"name": "name", "type": "string"}, 
     {"name": "favorite_number", "type": ["int", "null"]}, 
     {"name": "favorite_color", "type": ["string", "null"]} 
    ] 
} 

Download avro-tools-1.8.1

그것은 가치가 무엇인지에 대한

Download others avro-tools

관련 문제