You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by cu...@apache.org on 2009/06/19 22:46:04 UTC
svn commit: r786660 - in /hadoop/avro/trunk: CHANGES.txt
src/java/org/apache/avro/Protocol.java src/java/org/apache/avro/Schema.java
Author: cutting
Date: Fri Jun 19 20:46:04 2009
New Revision: 786660
URL: http://svn.apache.org/viewvc?rev=786660&view=rev
Log:
AVRO-56. Use Jackson to generate JSON from Java.
Modified:
hadoop/avro/trunk/CHANGES.txt
hadoop/avro/trunk/src/java/org/apache/avro/Protocol.java
hadoop/avro/trunk/src/java/org/apache/avro/Schema.java
Modified: hadoop/avro/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/CHANGES.txt?rev=786660&r1=786659&r2=786660&view=diff
==============================================================================
--- hadoop/avro/trunk/CHANGES.txt (original)
+++ hadoop/avro/trunk/CHANGES.txt Fri Jun 19 20:46:04 2009
@@ -63,6 +63,8 @@
AVRO-53. Use Ivy to retrieve Java dependencies. (cutting)
+ AVRO-56. Use Jackson to generate JSON from Java. (cutting)
+
OPTIMIZATIONS
BUG FIXES
Modified: hadoop/avro/trunk/src/java/org/apache/avro/Protocol.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/Protocol.java?rev=786660&r1=786659&r2=786660&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/Protocol.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/Protocol.java Fri Jun 19 20:46:04 2009
@@ -19,6 +19,7 @@
import java.io.ByteArrayInputStream;
import java.io.File;
+import java.io.StringWriter;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.ArrayList;
@@ -30,6 +31,7 @@
import org.apache.avro.Schema.Field;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParser;
+import org.codehaus.jackson.JsonGenerator;
/** A set of messages forming an application protocol.
* <p> A protocol consists of:
@@ -76,28 +78,33 @@
public Schema getErrors() { return errors; }
public String toString() {
- StringBuilder buffer = new StringBuilder();
- buffer.append("{\"request\": [");
- int count = 0;
- for (Map.Entry<String, Schema> entry : request.getFieldSchemas()) {
- buffer.append("{\"name\": \"");
- buffer.append(entry.getKey());
- buffer.append("\", \"type\": ");
- buffer.append(entry.getValue().toString(types));
- buffer.append("}");
- if (++count < request.getFields().size())
- buffer.append(", ");
+ try {
+ StringWriter writer = new StringWriter();
+ JsonGenerator gen = Schema.FACTORY.createJsonGenerator(writer);
+ toJson(gen);
+ gen.flush();
+ return writer.toString();
+ } catch (IOException e) {
+ throw new AvroRuntimeException(e);
}
- buffer.append("], \"response\": "+response.toString(types));
+ }
+ void toJson(JsonGenerator gen) throws IOException {
+ gen.writeStartObject();
+
+ gen.writeFieldName("request");
+ request.fieldsToJson(types, gen);
+
+ gen.writeFieldName("response");
+ response.toJson(types, gen);
List<Schema> errTypes = errors.getTypes(); // elide system error
if (errTypes.size() > 1) {
Schema errs = Schema.createUnion(errTypes.subList(1, errTypes.size()));
- buffer.append(", \"errors\": "+errs.toString(types));
+ gen.writeFieldName("errors");
+ errs.toJson(types, gen);
}
- buffer.append("}");
- return buffer.toString();
+ gen.writeEndObject();
}
public boolean equals(Object o) {
@@ -174,26 +181,33 @@
}
public String toString() {
- StringBuilder buffer = new StringBuilder();
- buffer.append("{\n");
- buffer.append("\"protocol\": \""+name+"\", \n");
- buffer.append("\"namespace\": \""+namespace+"\", \n");
- buffer.append("\"types\": [\n");
- int count = 0;
- int size = types.size();
- for (Schema type : types.values()) {
- buffer.append(type.toString(types.except(type.getName()))+"\n");
- if (++count < size) buffer.append(",\n");
+ try {
+ StringWriter writer = new StringWriter();
+ JsonGenerator gen = Schema.FACTORY.createJsonGenerator(writer);
+ toJson(gen);
+ gen.flush();
+ return writer.toString();
+ } catch (IOException e) {
+ throw new AvroRuntimeException(e);
}
- buffer.append("], \"messages\": {\n");
- count = 0;
+ }
+ void toJson(JsonGenerator gen) throws IOException {
+ gen.writeStartObject();
+ gen.writeStringField("protocol", name);
+ gen.writeStringField("namespace", namespace);
+
+ gen.writeArrayFieldStart("types");
+ for (Schema type : types.values())
+ type.toJson(types.except(type.getName()), gen);
+ gen.writeEndArray();
+
+ gen.writeObjectFieldStart("messages");
for (Map.Entry<String,Message> e : messages.entrySet()) {
- buffer.append("\""+e.getKey()+"\": "+e.getValue());
- if (++count < messages.size())
- buffer.append(",\n");
+ gen.writeFieldName(e.getKey());
+ e.getValue().toJson(gen);
}
- buffer.append("}\n}");
- return buffer.toString();
+ gen.writeEndObject();
+ gen.writeEndObject();
}
/** Return the MD5 hash of the text of this protocol. */
Modified: hadoop/avro/trunk/src/java/org/apache/avro/Schema.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/Schema.java?rev=786660&r1=786659&r2=786660&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/Schema.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/Schema.java Fri Jun 19 20:46:04 2009
@@ -20,6 +20,7 @@
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
+import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -33,6 +34,7 @@
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonParser;
+import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.ObjectMapper;
/** An abstract data type.
@@ -55,11 +57,12 @@
* </ul>
*/
public abstract class Schema {
- static final ObjectMapper MAPPER = new ObjectMapper();
static final JsonFactory FACTORY = new JsonFactory();
+ static final ObjectMapper MAPPER = new ObjectMapper(FACTORY);
static {
FACTORY.enableParserFeature(JsonParser.Feature.ALLOW_COMMENTS);
+ FACTORY.setCodec(MAPPER);
}
/** The type of a schema. */
@@ -155,12 +158,12 @@
/** If this is a record, enum or fixed, returns its name, if any. */
public String getName() {
- throw new AvroRuntimeException("Not a record or enum: "+this);
+ throw new AvroRuntimeException("Not a named type: "+this);
}
/** If this is a record, enum or fixed, returns its namespace, if any. */
public String getNamespace() {
- throw new AvroRuntimeException("Not a record or enum: "+this);
+ throw new AvroRuntimeException("Not a named type: "+this);
}
/** Returns true if this record is an error type. */
@@ -189,10 +192,24 @@
}
/** Render this as <a href="http://json.org/">JSON</a>.*/
- public String toString() { return toString(new Names()); }
+ public String toString() {
+ try {
+ StringWriter writer = new StringWriter();
+ JsonGenerator gen = FACTORY.createJsonGenerator(writer);
+ toJson(new Names(), gen);
+ gen.flush();
+ return writer.toString();
+ } catch (IOException e) {
+ throw new AvroRuntimeException(e);
+ }
+ }
+
+ abstract void toJson(Names names, JsonGenerator gen) throws IOException;
+
+ void fieldsToJson(Names names, JsonGenerator gen) throws IOException {
+ throw new AvroRuntimeException("Not a record: "+this);
+ }
- /** Render this, resolving names.*/
- String toString(Names names) { return toString(); }
public boolean equals(Object o) {
if (o == this) return true;
@@ -236,10 +253,19 @@
}
public String getName() { return name; }
public String getNamespace() { return space; }
- public String nameString(Names names) {
- return (name==null?"":"\"name\": \""+name+"\", ")
- +((space==null||space.equals(names.space()))
- ?"":"\"namespace\": \""+space+"\", ");
+ public boolean writeNameRef(Names names, JsonGenerator gen)
+ throws IOException {
+ if (this.equals(names.get(name))) {
+ gen.writeString(name);
+ return true;
+ } else if (name != null) {
+ names.put(name, this);
+ }
+ return false;
+ }
+ public void writeName(Names names, JsonGenerator gen) throws IOException {
+ if (name != null) gen.writeStringField("name", name);
+ if (space != null) gen.writeStringField("namespace", space);
}
public boolean equalNames(NamedSchema that) {
return that == null ? false
@@ -326,28 +352,30 @@
seen.remove(this);
}
}
- public String toString(Names names) {
- if (this.equals(names.get(name))) return "\""+name+"\"";
- else if (name != null) names.put(name, this);
- StringBuilder buffer = new StringBuilder();
- buffer.append("{\"type\": \""+(isError?"error":"record")+"\", "
- +nameString(names) +"\"fields\": [");
- int count = 0;
+ void toJson(Names names, JsonGenerator gen) throws IOException {
+ if (writeNameRef(names, gen)) return;
+ gen.writeStartObject();
+ gen.writeStringField("type", isError?"error":"record");
+ writeName(names, gen);
+ gen.writeFieldName("fields");
+ fieldsToJson(names, gen);
+ gen.writeEndObject();
+ }
+
+ void fieldsToJson(Names names, JsonGenerator gen) throws IOException {
+ gen.writeStartArray();
for (Map.Entry<String, Field> entry : fields.entrySet()) {
- buffer.append("{\"name\": \"");
- buffer.append(entry.getKey());
- buffer.append("\", \"type\": ");
- buffer.append(entry.getValue().schema().toString(names));
+ gen.writeStartObject();
+ gen.writeStringField("name", entry.getKey());
+ gen.writeFieldName("type");
+ entry.getValue().schema().toJson(names, gen);
if (entry.getValue().defaultValue() != null) {
- buffer.append(", \"default\": ");
- buffer.append(entry.getValue().defaultValue());
+ gen.writeFieldName("default");
+ gen.writeTree(entry.getValue().defaultValue());
}
- buffer.append("}");
- if (++count < fields.size())
- buffer.append(", ");
+ gen.writeEndObject();
}
- buffer.append("]}");
- return buffer.toString();
+ gen.writeEndArray();
}
}
@@ -371,21 +399,16 @@
return equalNames(that) && symbols.equals(that.symbols);
}
public int hashCode() { return super.hashCode() + symbols.hashCode(); }
- public String toString(Names names) {
- if (this.equals(names.get(name))) return "\""+name+"\"";
- else if (name != null) names.put(name, this);
- StringBuilder buffer = new StringBuilder();
- buffer.append("{\"type\": \"enum\", "
- +(name!=null?"\"name\": \""+name+"\", ":"")
- +"\"symbols\": [");
- int count = 0;
- for (String symbol : symbols) {
- buffer.append("\""+symbol+"\"");
- if (++count < symbols.size())
- buffer.append(", ");
- }
- buffer.append("]}");
- return buffer.toString();
+ void toJson(Names names, JsonGenerator gen) throws IOException {
+ if (writeNameRef(names, gen)) return;
+ gen.writeStartObject();
+ gen.writeStringField("type", "enum");
+ writeName(names, gen);
+ gen.writeArrayFieldStart("symbols");
+ for (String symbol : symbols)
+ gen.writeString(symbol);
+ gen.writeEndArray();
+ gen.writeEndObject();
}
}
@@ -402,12 +425,12 @@
&& elementType.equals(((ArraySchema)o).elementType);
}
public int hashCode() {return getType().hashCode()+elementType.hashCode();}
- public String toString(Names names) {
- StringBuilder buffer = new StringBuilder();
- buffer.append("{\"type\": \"array\", \"items\": ");
- buffer.append(elementType.toString(names));
- buffer.append("}");
- return buffer.toString();
+ void toJson(Names names, JsonGenerator gen) throws IOException {
+ gen.writeStartObject();
+ gen.writeStringField("type", "array");
+ gen.writeFieldName("items");
+ elementType.toJson(names, gen);
+ gen.writeEndObject();
}
}
@@ -426,12 +449,12 @@
public int hashCode() {
return getType().hashCode()+valueType.hashCode();
}
- public String toString(Names names) {
- StringBuilder buffer = new StringBuilder();
- buffer.append("{\"type\": \"map\", \"values\": ");
- buffer.append(valueType.toString(names));
- buffer.append("}");
- return buffer.toString();
+ void toJson(Names names, JsonGenerator gen) throws IOException {
+ gen.writeStartObject();
+ gen.writeStringField("type", "map");
+ gen.writeFieldName("values");
+ valueType.toJson(names, gen);
+ gen.writeEndObject();
}
}
@@ -462,17 +485,11 @@
return o instanceof UnionSchema && types.equals(((UnionSchema)o).types);
}
public int hashCode() {return getType().hashCode()+types.hashCode();}
- public String toString(Names names) {
- StringBuilder buffer = new StringBuilder();
- buffer.append("[");
- int count = 0;
- for (Schema type : types) {
- buffer.append(type.toString(names));
- if (++count < types.size())
- buffer.append(", ");
- }
- buffer.append("]");
- return buffer.toString();
+ void toJson(Names names, JsonGenerator gen) throws IOException {
+ gen.writeStartArray();
+ for (Schema type : types)
+ type.toJson(names, gen);
+ gen.writeEndArray();
}
}
@@ -489,53 +506,70 @@
return equalNames(that) && size == that.size;
}
public int hashCode() { return super.hashCode() + size; }
- public String toString(Names names) {
- if (this.equals(names.get(name))) return "\""+name+"\"";
- else if (name != null) names.put(name, this);
- return "{\"type\": \"fixed\", "
- +(name!=null?"\"name\": \""+name+"\", ":"")
- +"\"size\": "+size+"}";
+ void toJson(Names names, JsonGenerator gen) throws IOException {
+ if (writeNameRef(names, gen)) return;
+ gen.writeStartObject();
+ gen.writeStringField("type", "fixed");
+ writeName(names, gen);
+ gen.writeNumberField("size", size);
+ gen.writeEndObject();
}
}
private static class StringSchema extends Schema {
public StringSchema() { super(Type.STRING); }
- public String toString() { return "\"string\""; }
+ void toJson(Names names, JsonGenerator gen) throws IOException {
+ gen.writeString("string");
+ }
}
private static class BytesSchema extends Schema {
public BytesSchema() { super(Type.BYTES); }
- public String toString() { return "\"bytes\""; }
+ void toJson(Names names, JsonGenerator gen) throws IOException {
+ gen.writeString("bytes");
+ }
}
private static class IntSchema extends Schema {
public IntSchema() { super(Type.INT); }
- public String toString() { return "\"int\""; }
+ void toJson(Names names, JsonGenerator gen) throws IOException {
+ gen.writeString("int");
+ }
}
private static class LongSchema extends Schema {
public LongSchema() { super(Type.LONG); }
- public String toString() { return "\"long\""; }
+ void toJson(Names names, JsonGenerator gen) throws IOException {
+ gen.writeString("long");
+ }
}
private static class FloatSchema extends Schema {
public FloatSchema() { super(Type.FLOAT); }
- public String toString() { return "\"float\""; }
+ void toJson(Names names, JsonGenerator gen) throws IOException {
+ gen.writeString("float");
+ }
}
private static class DoubleSchema extends Schema {
public DoubleSchema() { super(Type.DOUBLE); }
- public String toString() { return "\"double\""; }
+ void toJson(Names names, JsonGenerator gen) throws IOException {
+ gen.writeString("double");
+ }
}
private static class BooleanSchema extends Schema {
public BooleanSchema() { super(Type.BOOLEAN); }
- public String toString() { return "\"boolean\""; }
+ void toJson(Names names, JsonGenerator gen) throws IOException {
+ gen.writeString("boolean");
+ }
}
private static class NullSchema extends Schema {
public NullSchema() { super(Type.NULL); }
- public String toString() { return "\"null\""; }
+ void toJson(Names names, JsonGenerator gen) throws IOException {
+ gen.writeString("null");
+ }
}
private static final StringSchema STRING_SCHEMA = new StringSchema();