package org.apache.avro.tool; import static com.google.common.base.Preconditions.checkNotNull; import com.fasterxml.jackson.databind.ObjectMapper; import joptsimple.OptionParser; import joptsimple.OptionSet; import joptsimple.OptionSpec; import org.apache.avro.file.DataFileStream; import org.apache.avro.generic.GenericDatumReader; import org.apache.avro.generic.GenericRecord; import java.io.BufferedInputStream; import java.io.InputStream; import java.io.PrintStream; import java.nio.ByteBuffer; import java.util.List; public class ProtoToJsonTool implements Tool { @Override public String getName() { return "tojson"; } @Override public String getShortDescription() { return "Dumps a Protobuf in Avro data file as JSON, record per line or pretty."; } @Override public int run(InputStream in, PrintStream out, PrintStream err, List<String> args) throws Exception { OptionParser optionParser = new OptionParser(); OptionSpec<Void> prettyOption = optionParser .accepts("pretty", "Turns on pretty printing."); OptionSet optionSet = optionParser.parse(args.toArray(new String[0])); Boolean pretty = optionSet.has(prettyOption); List<String> nargs = (List<String>)optionSet.nonOptionArguments(); if (nargs.size() != 1) { printHelp(err); err.println(); optionParser.printHelpOn(err); return 1; } BufferedInputStream inStream = Util.fileOrStdin(nargs.get(0), in); GenericDatumReader<Object> reader = new GenericDatumReader<>(); DataFileStream<Object> streamReader = new DataFileStream<>(inStream, reader); ObjectMapper mapper = new ObjectMapper(); try { String schema = streamReader.getMetaString("protobuf.generic.schema"); checkNotNull(schema, "Missing metadata key protobuf.generic.schema"); ProtobufReader protoReader = new ProtobufReader(schema); for (Object datum : streamReader) { ByteBuffer byteBuffer = (ByteBuffer) ((GenericRecord) datum).get("bytes"); String json = protoReader.toJson(byteBuffer); if (pretty) { String prettyJson = mapper .writerWithDefaultPrettyPrinter() .writeValueAsString(mapper.readValue(json, Object.class)); out.println(prettyJson); } else { out.println(json); } } out.println(); out.flush(); } finally { streamReader.close(); } return 0; } private void printHelp(PrintStream ps) { ps.println("tojson --pretty input-file"); ps.println(); ps.println(getShortDescription()); ps.println("A dash ('-') can be given as an input file to use stdin"); } }