You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by to...@apache.org on 2014/11/18 10:58:22 UTC

svn commit: r1640293 - in /avro/trunk: ./ lang/java/ lang/java/avro/src/main/java/org/apache/avro/ lang/java/avro/src/main/java/org/apache/avro/data/ lang/java/avro/src/main/java/org/apache/avro/io/ lang/java/avro/src/main/java/org/apache/avro/io/parsi...

Author: tomwhite
Date: Tue Nov 18 09:58:21 2014
New Revision: 1640293

URL: http://svn.apache.org/r1640293
Log:
AVRO-1585. Java: Deprecate Jackson classes in public API.

Added:
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/util/internal/
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/util/internal/JacksonUtils.java
    avro/trunk/lang/java/avro/src/test/java/org/apache/avro/util/internal/
    avro/trunk/lang/java/avro/src/test/java/org/apache/avro/util/internal/TestJacksonUtils.java
Modified:
    avro/trunk/CHANGES.txt
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/JsonProperties.java
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/Schema.java
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/data/Json.java
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/io/EncoderFactory.java
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/io/JsonEncoder.java
    avro/trunk/lang/java/avro/src/main/java/org/apache/avro/io/parsing/ResolvingGrammarGenerator.java
    avro/trunk/lang/java/avro/src/test/java/org/apache/avro/TestSchemaBuilder.java
    avro/trunk/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibility.java
    avro/trunk/lang/java/avro/src/test/java/org/apache/avro/generic/TestGenericRecordBuilder.java
    avro/trunk/lang/java/ipc/src/test/java/org/apache/avro/TestProtocolGeneric.java
    avro/trunk/lang/java/ipc/src/test/java/org/apache/avro/TestSchema.java
    avro/trunk/lang/java/mapred/src/test/java/org/apache/avro/mapred/TestGenericJob.java
    avro/trunk/lang/java/pom.xml
    avro/trunk/lang/java/tools/src/main/java/org/apache/avro/tool/RpcReceiveTool.java

Modified: avro/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/avro/trunk/CHANGES.txt?rev=1640293&r1=1640292&r2=1640293&view=diff
==============================================================================
--- avro/trunk/CHANGES.txt (original)
+++ avro/trunk/CHANGES.txt Tue Nov 18 09:58:21 2014
@@ -45,6 +45,8 @@ Trunk (not yet released)
     AVRO-1551. Java: Add an output encoding option to the compiler
     command line tool. (Keegan Witt via cutting)
 
+    AVRO-1585. Java: Deprecate Jackson classes in public API. (tomwhite)
+
   BUG FIXES
 
     AVRO-1553. Java: MapReduce never uses MapOutputValueSchema (tomwhite)

Modified: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/JsonProperties.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/JsonProperties.java?rev=1640293&r1=1640292&r2=1640293&view=diff
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/JsonProperties.java (original)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/JsonProperties.java Tue Nov 18 09:58:21 2014
@@ -23,12 +23,97 @@ import java.util.Map;
 import java.util.Set;
 import java.io.IOException;
 
+import org.apache.avro.util.internal.JacksonUtils;
 import org.codehaus.jackson.JsonNode;
 import org.codehaus.jackson.JsonGenerator;
 import org.codehaus.jackson.node.TextNode;
 
-/** Base class for objects that have Json-valued properties. */
+/**
+ * Base class for objects that have JSON-valued properties. Avro and JSON values are
+ * represented in Java using the following mapping:
+ * 
+ * <table>
+ *   <th>
+ *     <td>Avro type</td>
+ *     <td>JSON type</td>
+ *     <td>Java type</td>
+ *   </th>
+ *   <tr>
+ *     <td><code>null</code></td>
+ *     <td><code>null</code></td>
+ *     <td>{@link #NULL_VALUE}</td>
+ *   </tr>
+ *   <tr>
+ *     <td><code>boolean</code></td>
+ *     <td>Boolean</td>
+ *     <td><code>boolean</code></td>
+ *   </tr>
+ *   <tr>
+ *     <td><code>int</code></td>
+ *     <td>Number</td>
+ *     <td><code>int</code></td>
+ *   </tr>
+ *   <tr>
+ *     <td><code>long</code></td>
+ *     <td>Number</td>
+ *     <td><code>long</code></td>
+ *   </tr>
+ *   <tr>
+ *     <td><code>float</code></td>
+ *     <td>Number</td>
+ *     <td><code>float</code></td>
+ *   </tr>
+ *   <tr>
+ *     <td><code>double</code></td>
+ *     <td>Number</td>
+ *     <td><code>double</code></td>
+ *   </tr>
+ *   <tr>
+ *     <td><code>bytes</code></td>
+ *     <td>String</td>
+ *     <td><code>byte[]</code></td>
+ *   </tr>
+ *   <tr>
+ *     <td><code>string</code></td>
+ *     <td>String</td>
+ *     <td>{@link java.lang.String}</td>
+ *   </tr>
+ *   <tr>
+ *     <td><code>record</code></td>
+ *     <td>Object</td>
+ *     <td>{@link java.util.Map}</td>
+ *   </tr>
+ *   <tr>
+ *     <td><code>enum</code></td>
+ *     <td>String</td>
+ *     <td>{@link java.lang.String}</td>
+ *   </tr>
+ *   <tr>
+ *     <td><code>array</code></td>
+ *     <td>Array</td>
+ *     <td>{@link java.util.Collection}</td>
+ *   </tr>
+ *   <tr>
+ *     <td><code>map</code></td>
+ *     <td>Object</td>
+ *     <td>{@link java.util.Map}</td>
+ *   </tr>
+ *   <tr>
+ *     <td><code>fixed</code></td>
+ *     <td>String</td>
+ *     <td><code>byte[]</code></td>
+ *   </tr>
+ * </table>
+ *
+ * @see org.apache.avro.data.Json
+ */
 public abstract class JsonProperties {
+  public static class Null {
+    private Null() {}
+  }
+  /** A value representing a JSON <code>null</code>. */
+  public static final Null NULL_VALUE = new Null();
+
   Map<String,JsonNode> props = new LinkedHashMap<String,JsonNode>(1);
 
   private Set<String> reserved;
@@ -49,12 +134,22 @@ public abstract class JsonProperties {
   /**
    * Returns the value of the named property in this schema.
    * Returns <tt>null</tt> if there is no property with that name.
+   * @deprecated use {@link #getObjectProp(String)}
    */
+  @Deprecated
   public synchronized JsonNode getJsonProp(String name) {
     return props.get(name);
   }
 
   /**
+   * Returns the value of the named property in this schema.
+   * Returns <tt>null</tt> if there is no property with that name.
+   */
+  public synchronized Object getObjectProp(String name) {
+    return JacksonUtils.toObject(props.get(name));
+  }
+
+  /**
    * Adds a property with the given name <tt>name</tt> and
    * value <tt>value</tt>. Neither <tt>name</tt> nor <tt>value</tt> can be
    * <tt>null</tt>. It is illegal to add a property if another with
@@ -75,7 +170,9 @@ public abstract class JsonProperties {
    * 
    * @param name The name of the property to add
    * @param value The value for the property to add
+   * @deprecated use {@link #addProp(String, Object)}
    */
+  @Deprecated
   public synchronized void addProp(String name, JsonNode value) {
     if (reserved.contains(name))
       throw new AvroRuntimeException("Can't set reserved property: " + name);
@@ -90,6 +187,10 @@ public abstract class JsonProperties {
       throw new AvroRuntimeException("Can't overwrite property: " + name);
   }
 
+  public synchronized void addProp(String name, Object value) {
+    addProp(name, JacksonUtils.toJsonNode(value));
+  }
+
   /** Return the defined properties that have string values. */
   @Deprecated public Map<String,String> getProps() {
     Map<String,String> result = new LinkedHashMap<String,String>();
@@ -107,11 +208,23 @@ public abstract class JsonProperties {
     return result;
   }
 
-  /** Return the defined properties as an unmodifieable Map. */
+  /**
+   * Return the defined properties as an unmodifieable Map.
+   * @deprecated use {@link #getObjectProps()}
+   */
+  @Deprecated
   public Map<String,JsonNode> getJsonProps() {
     return Collections.unmodifiableMap(props);
   }
 
+  /** Return the defined properties as an unmodifieable Map. */
+  public Map<String,Object> getObjectProps() {
+    Map<String,Object> result = new LinkedHashMap<String,Object>();
+    for (Map.Entry<String,JsonNode> e : props.entrySet())
+      result.put(e.getKey(), JacksonUtils.toObject(e.getValue()));
+    return result;
+  }
+
   void writeProps(JsonGenerator gen) throws IOException {
     for (Map.Entry<String,JsonNode> e : props.entrySet())
       gen.writeObjectField(e.getKey(), e.getValue());

Modified: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/Schema.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/Schema.java?rev=1640293&r1=1640292&r2=1640293&view=diff
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/Schema.java (original)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/Schema.java Tue Nov 18 09:58:21 2014
@@ -35,6 +35,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.avro.util.internal.JacksonUtils;
 import org.codehaus.jackson.JsonFactory;
 import org.codehaus.jackson.JsonNode;
 import org.codehaus.jackson.JsonParseException;
@@ -132,6 +133,11 @@ public abstract class Schema extends Jso
     hashCode = NO_HASHCODE;
   }
 
+  @Override public void addProp(String name, Object value) {
+    super.addProp(name, value);
+    hashCode = NO_HASHCODE;
+  }
+
   /** Create an anonymous record schema. */
   public static Schema createRecord(List<Field> fields) {
     Schema result = createRecord(null, null, null, false);
@@ -362,10 +368,14 @@ public abstract class Schema extends Jso
     private final Order order;
     private Set<String> aliases;
 
+    /** @deprecated use {@link #Field(String, Schema, String, Object)} */
+    @Deprecated
     public Field(String name, Schema schema, String doc,
         JsonNode defaultValue) {
       this(name, schema, doc, defaultValue, Order.ASCENDING);
     }
+    /** @deprecated use {@link #Field(String, Schema, String, Object, Order)} */
+    @Deprecated
     public Field(String name, Schema schema, String doc,
         JsonNode defaultValue, Order order) {
       super(FIELD_RESERVED);
@@ -375,6 +385,22 @@ public abstract class Schema extends Jso
       this.defaultValue = validateDefault(name, schema, defaultValue);
       this.order = order;
     }
+    /**
+     * @param defaultValue the default value for this field specified using the mapping
+     *  in {@link JsonProperties}
+     */
+    public Field(String name, Schema schema, String doc,
+        Object defaultValue) {
+      this(name, schema, doc, defaultValue, Order.ASCENDING);
+    }
+    /**
+     * @param defaultValue the default value for this field specified using the mapping
+     *  in {@link JsonProperties}
+     */
+    public Field(String name, Schema schema, String doc,
+        Object defaultValue, Order order) {
+      this(name, schema, doc, JacksonUtils.toJsonNode(defaultValue), order);
+    }
     public String name() { return name; };
     /** The position of this field within the record. */
     public int pos() { return position; }
@@ -382,7 +408,13 @@ public abstract class Schema extends Jso
     public Schema schema() { return schema; }
     /** Field's documentation within the record, if set. May return null. */
     public String doc() { return doc; }
-    public JsonNode defaultValue() { return defaultValue; }
+    /** @deprecated use {@link #defaultVal() } */
+    @Deprecated public JsonNode defaultValue() { return defaultValue; }
+    /**
+     * @return the default value for this field specified using the mapping
+     *  in {@link JsonProperties}
+     */
+    public Object defaultVal() { return JacksonUtils.toObject(defaultValue); }
     public Order order() { return order; }
     @Deprecated public Map<String,String> props() { return getProps(); }
     public void addAlias(String alias) {
@@ -1313,7 +1345,11 @@ public abstract class Schema extends Jso
     return jsonNode != null ? jsonNode.getTextValue() : null;
   }
 
-  /** Parses a string as Json. */
+  /**
+   * Parses a string as Json.
+   * @deprecated use {@link org.apache.avro.data.Json#parseJson(String)}
+   */
+  @Deprecated
   public static JsonNode parseJson(String s) {
     try {
       return MAPPER.readTree(FACTORY.createJsonParser(new StringReader(s)));

Modified: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/data/Json.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/data/Json.java?rev=1640293&r1=1640292&r2=1640293&view=diff
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/data/Json.java (original)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/data/Json.java Tue Nov 18 09:58:21 2014
@@ -18,9 +18,14 @@
 package org.apache.avro.data;
 
 import java.io.IOException;
+import java.io.StringReader;
 import java.util.Iterator;
 
+import org.apache.avro.util.internal.JacksonUtils;
+import org.codehaus.jackson.JsonFactory;
 import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.map.ObjectMapper;
 import org.codehaus.jackson.node.JsonNodeFactory;
 import org.codehaus.jackson.node.LongNode;
 import org.codehaus.jackson.node.DoubleNode;
@@ -43,6 +48,9 @@ import org.apache.avro.io.ResolvingDecod
 public class Json {
   private Json() {}                               // singleton: no public ctor
 
+  static final JsonFactory FACTORY = new JsonFactory();
+  static final ObjectMapper MAPPER = new ObjectMapper(FACTORY);
+
   /** The schema for Json data. */
   public static final Schema SCHEMA;
   static {
@@ -54,7 +62,11 @@ public class Json {
     }
   }
 
-  /** {@link DatumWriter} for arbitrary Json data. */
+  /**
+   * {@link DatumWriter} for arbitrary Json data.
+   * @deprecated use {@link ObjectWriter}
+   */
+  @Deprecated
   public static class Writer implements DatumWriter<JsonNode> {
 
     @Override public void setSchema(Schema schema) {
@@ -68,7 +80,11 @@ public class Json {
     }
   }
 
-  /** {@link DatumReader} for arbitrary Json data. */
+  /**
+   * {@link DatumReader} for arbitrary Json data.
+   * @deprecated use {@link ObjectReader}
+   */
+  @Deprecated
   public static class Reader implements DatumReader<JsonNode> {
     private Schema written;
     private ResolvingDecoder resolver;
@@ -92,10 +108,77 @@ public class Json {
     }
   }
 
+  /** {@link DatumWriter} for arbitrary Json data using the object model described
+   *  in {@link org.apache.avro.JsonProperties}. */
+  public static class ObjectWriter implements DatumWriter<Object> {
+
+    @Override public void setSchema(Schema schema) {
+      if (!SCHEMA.equals(schema))
+        throw new RuntimeException("Not the Json schema: "+schema);
+    }
+
+    @Override
+    public void write(Object datum, Encoder out) throws IOException {
+      Json.writeObject(datum, out);
+    }
+  }
+
+  /** {@link DatumReader} for arbitrary Json data using the object model described
+   *  in {@link org.apache.avro.JsonProperties}. */
+  public static class ObjectReader implements DatumReader<Object> {
+    private Schema written;
+    private ResolvingDecoder resolver;
+
+    @Override public void setSchema(Schema schema) {
+      this.written = SCHEMA.equals(written) ? null : schema;
+    }
+
+    @Override
+    public Object read(Object reuse, Decoder in) throws IOException {
+      if (written == null)                        // same schema
+        return Json.readObject(in);
+
+      // use a resolver to adapt alternate version of Json schema
+      if (resolver == null)
+        resolver = DecoderFactory.get().resolvingDecoder(written, SCHEMA, null);
+      resolver.configure(in);
+      Object result = Json.readObject(resolver);
+      resolver.drain();
+      return result;
+    }
+  }
+
+  /**
+   * Parses a JSON string and converts it to the object model described in
+   * {@link org.apache.avro.JsonProperties}.
+   */
+  public static Object parseJson(String s) {
+    try {
+      return JacksonUtils.toObject(MAPPER.readTree(FACTORY.createJsonParser(
+          new StringReader(s))));
+    } catch (JsonParseException e) {
+      throw new RuntimeException(e);
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  /**
+   * Converts an instance of the object model described in
+   * {@link org.apache.avro.JsonProperties} to a JSON string.
+   */
+  public static String toString(Object datum) {
+    return JacksonUtils.toJsonNode(datum).toString();
+  }
+
   /** Note: this enum must be kept aligned with the union in Json.avsc. */
   private enum JsonType { LONG, DOUBLE, STRING, BOOLEAN, NULL, ARRAY, OBJECT }
   
-  /** Write Json data as Avro data. */
+  /**
+   * Write Json data as Avro data.
+   * @deprecated internal method
+   */
+  @Deprecated
   public static void write(JsonNode node, Encoder out) throws IOException {
     switch(node.asToken()) {
     case VALUE_NUMBER_INT:
@@ -150,7 +233,11 @@ public class Json {
     }
   }
 
-  /** Read Json data from Avro data. */
+  /**
+   * Read Json data from Avro data.
+   * @deprecated internal method
+   */
+  @Deprecated
   public static JsonNode read(Decoder in) throws IOException {
     switch (JsonType.values()[in.readIndex()]) {
     case LONG:
@@ -181,4 +268,12 @@ public class Json {
     }
   }
 
+  private static void writeObject(Object datum, Encoder out) throws IOException {
+    write(JacksonUtils.toJsonNode(datum), out);
+  }
+
+  private static Object readObject(Decoder in) throws IOException {
+    return JacksonUtils.toObject(read(in));
+  }
+
 }

Modified: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/io/EncoderFactory.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/io/EncoderFactory.java?rev=1640293&r1=1640292&r2=1640293&view=diff
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/io/EncoderFactory.java (original)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/io/EncoderFactory.java Tue Nov 18 09:58:21 2014
@@ -320,7 +320,9 @@ public class EncoderFactory {
    *          The JsonGenerator to write with. Cannot be null.
    * @return A JsonEncoder configured with <i>gen</i> and <i>schema</i>
    * @throws IOException
+   * @deprecated internal method
    */
+  @Deprecated
   public JsonEncoder jsonEncoder(Schema schema, JsonGenerator gen)
       throws IOException {
     return new JsonEncoder(schema, gen);

Modified: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/io/JsonEncoder.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/io/JsonEncoder.java?rev=1640293&r1=1640292&r2=1640293&view=diff
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/io/JsonEncoder.java (original)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/io/JsonEncoder.java Tue Nov 18 09:58:21 2014
@@ -131,7 +131,9 @@ public class JsonEncoder extends Parsing
    *          The JsonGenerator to direct output to. Cannot be null.
    * @throws IOException
    * @return this JsonEncoder
+   * @deprecated internal method
    */
+  @Deprecated
   public JsonEncoder configure(JsonGenerator generator) throws IOException {
     if (null == generator)
       throw new NullPointerException("JsonGenerator cannot be null");

Modified: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/io/parsing/ResolvingGrammarGenerator.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/io/parsing/ResolvingGrammarGenerator.java?rev=1640293&r1=1640292&r2=1640293&view=diff
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/io/parsing/ResolvingGrammarGenerator.java (original)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/io/parsing/ResolvingGrammarGenerator.java Tue Nov 18 09:58:21 2014
@@ -316,8 +316,9 @@ public class ResolvingGrammarGenerator e
    * @param s The schema for the object being encoded.
    * @param n The Json node to encode.
    * @throws IOException
+   * @deprecated internal method
    */
-  
+  @Deprecated
   public static void encode(Encoder e, Schema s, JsonNode n)
     throws IOException {
     switch (s.getType()) {

Added: avro/trunk/lang/java/avro/src/main/java/org/apache/avro/util/internal/JacksonUtils.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/util/internal/JacksonUtils.java?rev=1640293&view=auto
==============================================================================
--- avro/trunk/lang/java/avro/src/main/java/org/apache/avro/util/internal/JacksonUtils.java (added)
+++ avro/trunk/lang/java/avro/src/main/java/org/apache/avro/util/internal/JacksonUtils.java Tue Nov 18 09:58:21 2014
@@ -0,0 +1,136 @@
+package org.apache.avro.util.internal;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.avro.AvroRuntimeException;
+import org.apache.avro.JsonProperties;
+import org.apache.avro.Schema;
+import org.codehaus.jackson.JsonGenerator;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.util.TokenBuffer;
+
+public class JacksonUtils {
+  static final String BYTES_CHARSET = "ISO-8859-1";
+
+  private JacksonUtils() {
+  }
+
+  public static JsonNode toJsonNode(Object datum) {
+    if (datum == null) {
+      return null;
+    }
+    try {
+      TokenBuffer generator = new TokenBuffer(new ObjectMapper());
+      toJson(datum, generator);
+      return new ObjectMapper().readTree(generator.asParser());
+    } catch (IOException e) {
+      throw new AvroRuntimeException(e);
+    }
+  }
+
+  @SuppressWarnings(value="unchecked")
+  static void toJson(Object datum, JsonGenerator generator) throws IOException {
+    if (datum == JsonProperties.NULL_VALUE) { // null
+      generator.writeNull();
+    } else if (datum instanceof Map) { // record, map
+      generator.writeStartObject();
+      for (Map.Entry<Object,Object> entry : ((Map<Object,Object>) datum).entrySet()) {
+        generator.writeFieldName(entry.getKey().toString());
+        toJson(entry.getValue(), generator);
+      }
+      generator.writeEndObject();
+    } else if (datum instanceof Collection) { // array
+      generator.writeStartArray();
+      for (Object element : (Collection<?>) datum) {
+        toJson(element, generator);
+      }
+      generator.writeEndArray();
+    } else if (datum instanceof byte[]) { // bytes, fixed
+      generator.writeString(new String((byte[]) datum, BYTES_CHARSET));
+    } else if (datum instanceof CharSequence || datum instanceof Enum<?>) { // string, enum
+      generator.writeString(datum.toString());
+    } else if (datum instanceof Double) { // double
+      generator.writeNumber((Double) datum);
+    } else if (datum instanceof Float) { // float
+      generator.writeNumber((Float) datum);
+    } else if (datum instanceof Long) { // long
+      generator.writeNumber((Long) datum);
+    } else if (datum instanceof Integer) { // int
+      generator.writeNumber((Integer) datum);
+    } else if (datum instanceof Boolean) { // boolean
+      generator.writeBoolean((Boolean) datum);
+    }
+  }
+
+  public static Object toObject(JsonNode jsonNode) {
+    return toObject(jsonNode, null);
+  }
+
+  public static Object toObject(JsonNode jsonNode, Schema schema) {
+    if (schema != null && schema.getType().equals(Schema.Type.UNION)) {
+      return toObject(jsonNode, schema.getTypes().get(0));
+    }
+    if (jsonNode == null) {
+      return null;
+    } else if (jsonNode.isNull()) {
+      return JsonProperties.NULL_VALUE;
+    } else if (jsonNode.isBoolean()) {
+      return jsonNode.asBoolean();
+    } else if (jsonNode.isInt()) {
+      if (schema == null || schema.getType().equals(Schema.Type.INT)) {
+        return jsonNode.asInt();
+      } else if (schema.getType().equals(Schema.Type.LONG)) {
+        return jsonNode.asLong();
+      }
+    } else if (jsonNode.isLong()) {
+      return jsonNode.asLong();
+    } else if (jsonNode.isDouble()) {
+      if (schema == null || schema.getType().equals(Schema.Type.DOUBLE)) {
+        return jsonNode.asDouble();
+      } else if (schema.getType().equals(Schema.Type.FLOAT)) {
+        return (float) jsonNode.asDouble();
+      }
+    } else if (jsonNode.isTextual()) {
+      if (schema == null || schema.getType().equals(Schema.Type.STRING) ||
+          schema.getType().equals(Schema.Type.ENUM)) {
+        return jsonNode.asText();
+      } else if (schema.getType().equals(Schema.Type.BYTES)) {
+        try {
+          return jsonNode.getTextValue().getBytes(BYTES_CHARSET);
+        } catch (UnsupportedEncodingException e) {
+          throw new AvroRuntimeException(e);
+        }
+      }
+    } else if (jsonNode.isArray()) {
+      List l = new ArrayList();
+      for (JsonNode node : jsonNode) {
+        l.add(toObject(node, schema == null ? null : schema.getElementType()));
+      }
+      return l;
+    } else if (jsonNode.isObject()) {
+      Map m = new LinkedHashMap();
+      for (Iterator<String> it = jsonNode.getFieldNames(); it.hasNext(); ) {
+        String key = it.next();
+        Schema s = null;
+        if (schema == null) {
+          s = null;
+        } else if (schema.getType().equals(Schema.Type.MAP)) {
+          s = schema.getValueType();
+        } else if (schema.getType().equals(Schema.Type.RECORD)) {
+          s = schema.getField(key).schema();
+        }
+        Object value = toObject(jsonNode.get(key), s);
+        m.put(key, value);
+      }
+      return m;
+    }
+    return null;
+  }
+}

Modified: avro/trunk/lang/java/avro/src/test/java/org/apache/avro/TestSchemaBuilder.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/test/java/org/apache/avro/TestSchemaBuilder.java?rev=1640293&r1=1640292&r2=1640293&view=diff
==============================================================================
--- avro/trunk/lang/java/avro/src/test/java/org/apache/avro/TestSchemaBuilder.java (original)
+++ avro/trunk/lang/java/avro/src/test/java/org/apache/avro/TestSchemaBuilder.java Tue Nov 18 09:58:21 2014
@@ -33,7 +33,6 @@ import org.apache.avro.generic.GenericDa
 import org.apache.avro.generic.GenericDatumReader;
 import org.apache.avro.generic.GenericDatumWriter;
 import org.apache.avro.generic.GenericRecordBuilder;
-import org.codehaus.jackson.node.BooleanNode;
 import org.codehaus.jackson.node.NullNode;
 import org.junit.Assert;
 import org.junit.Test;
@@ -70,7 +69,7 @@ public class TestSchemaBuilder {
     types.add(Schema.create(Schema.Type.BOOLEAN));
     types.add(Schema.create(Schema.Type.NULL));
     Schema optional = Schema.createUnion(types);
-    Assert.assertEquals(new Schema.Field("f2", optional, null, BooleanNode.getTrue()),
+    Assert.assertEquals(new Schema.Field("f2", optional, null, true),
         fields.get(2));
   }
   

Modified: avro/trunk/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibility.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibility.java?rev=1640293&r1=1640292&r2=1640293&view=diff
==============================================================================
--- avro/trunk/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibility.java (original)
+++ avro/trunk/lang/java/avro/src/test/java/org/apache/avro/TestSchemaCompatibility.java Tue Nov 18 09:58:21 2014
@@ -38,7 +38,6 @@ import org.apache.avro.io.DecoderFactory
 import org.apache.avro.io.Encoder;
 import org.apache.avro.io.EncoderFactory;
 import org.apache.avro.util.Utf8;
-import org.codehaus.jackson.node.IntNode;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -118,13 +117,13 @@ public class TestSchemaCompatibility {
         new Field("a", INT_SCHEMA, null, null),
         new Field("b", INT_SCHEMA, null, null)));
     A_DINT_RECORD1.setFields(list(
-        new Field("a", INT_SCHEMA, null, new IntNode(0))));
+        new Field("a", INT_SCHEMA, null, 0)));
     A_INT_B_DINT_RECORD1.setFields(list(
         new Field("a", INT_SCHEMA, null, null),
-        new Field("b", INT_SCHEMA, null, new IntNode(0))));
+        new Field("b", INT_SCHEMA, null, 0)));
     A_DINT_B_DINT_RECORD1.setFields(list(
-        new Field("a", INT_SCHEMA, null, new IntNode(0)),
-        new Field("b", INT_SCHEMA, null, new IntNode(0))));
+        new Field("a", INT_SCHEMA, null, 0),
+        new Field("b", INT_SCHEMA, null, 0)));
   }
 
   // Recursive records
@@ -221,7 +220,7 @@ public class TestSchemaCompatibility {
   public void testValidateSchemaNewFieldWithDefault() throws Exception {
     final List<Schema.Field> readerFields = list(
         new Schema.Field("oldfield1", INT_SCHEMA, null, null),
-        new Schema.Field("newfield1", INT_SCHEMA, null, IntNode.valueOf(42)));
+        new Schema.Field("newfield1", INT_SCHEMA, null, 42));
     final Schema reader = Schema.createRecord(readerFields);
     final SchemaCompatibility.SchemaPairCompatibility expectedResult =
         new SchemaCompatibility.SchemaPairCompatibility(

Modified: avro/trunk/lang/java/avro/src/test/java/org/apache/avro/generic/TestGenericRecordBuilder.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/test/java/org/apache/avro/generic/TestGenericRecordBuilder.java?rev=1640293&r1=1640292&r2=1640293&view=diff
==============================================================================
--- avro/trunk/lang/java/avro/src/test/java/org/apache/avro/generic/TestGenericRecordBuilder.java (original)
+++ avro/trunk/lang/java/avro/src/test/java/org/apache/avro/generic/TestGenericRecordBuilder.java Tue Nov 18 09:58:21 2014
@@ -26,8 +26,6 @@ import org.apache.avro.Schema;
 import org.apache.avro.Schema.Field;
 import org.apache.avro.Schema.Type;
 import org.apache.avro.generic.GenericData.Record;
-import org.codehaus.jackson.node.TextNode;
-import org.codehaus.jackson.node.NullNode;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -100,13 +98,13 @@ public class TestGenericRecordBuilder {
   /** Creates a test record schema */
   private static Schema recordSchema() {
     List<Field> fields = new ArrayList<Field>();
-    fields.add(new Field("id", Schema.create(Type.STRING), null, new TextNode("0")));
+    fields.add(new Field("id", Schema.create(Type.STRING), null, "0"));
     fields.add(new Field("intField", Schema.create(Type.INT), null, null));
     fields.add(new Field("anArray", Schema.createArray(Schema.create(Type.STRING)), null, null));
     fields.add(new Field("optionalInt", Schema.createUnion
                          (Arrays.asList(Schema.create(Type.NULL),
                                         Schema.create(Type.INT))),
-                         null, NullNode.getInstance()));
+                         null, Schema.NULL_VALUE));
     Schema schema = Schema.createRecord("Foo", "test", "mytest", false);
     schema.setFields(fields);
     return schema;

Added: avro/trunk/lang/java/avro/src/test/java/org/apache/avro/util/internal/TestJacksonUtils.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/test/java/org/apache/avro/util/internal/TestJacksonUtils.java?rev=1640293&view=auto
==============================================================================
--- avro/trunk/lang/java/avro/src/test/java/org/apache/avro/util/internal/TestJacksonUtils.java (added)
+++ avro/trunk/lang/java/avro/src/test/java/org/apache/avro/util/internal/TestJacksonUtils.java Tue Nov 18 09:58:21 2014
@@ -0,0 +1,84 @@
+package org.apache.avro.util.internal;
+
+import java.util.Collections;
+import org.apache.avro.JsonProperties;
+import org.apache.avro.Schema;
+import org.apache.avro.SchemaBuilder;
+import org.codehaus.jackson.node.ArrayNode;
+import org.codehaus.jackson.node.BooleanNode;
+import org.codehaus.jackson.node.DoubleNode;
+import org.codehaus.jackson.node.IntNode;
+import org.codehaus.jackson.node.JsonNodeFactory;
+import org.codehaus.jackson.node.LongNode;
+import org.codehaus.jackson.node.NullNode;
+import org.codehaus.jackson.node.ObjectNode;
+import org.codehaus.jackson.node.TextNode;
+import org.junit.Test;
+
+import static org.apache.avro.util.internal.JacksonUtils.toJsonNode;
+import static org.apache.avro.util.internal.JacksonUtils.toObject;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+public class TestJacksonUtils {
+
+  enum Direction {
+    UP, DOWN;
+  }
+
+  @Test
+  public void testToJsonNode() {
+    assertEquals(null, toJsonNode(null));
+    assertEquals(NullNode.getInstance(), toJsonNode(JsonProperties.NULL_VALUE));
+    assertEquals(BooleanNode.TRUE, toJsonNode(true));
+    assertEquals(IntNode.valueOf(1), toJsonNode(1));
+    assertEquals(LongNode.valueOf(2), toJsonNode(2L));
+    assertEquals(DoubleNode.valueOf(1.0), toJsonNode(1.0f));
+    assertEquals(DoubleNode.valueOf(2.0), toJsonNode(2.0));
+    assertEquals(TextNode.valueOf("\u0001\u0002"), toJsonNode(new byte[] { 1, 2 }));
+    assertEquals(TextNode.valueOf("a"), toJsonNode("a"));
+    assertEquals(TextNode.valueOf("UP"), toJsonNode(Direction.UP));
+
+    ArrayNode an = JsonNodeFactory.instance.arrayNode();
+    an.add(1);
+    assertEquals(an, toJsonNode(Collections.singletonList(1)));
+
+    ObjectNode on = JsonNodeFactory.instance.objectNode();
+    on.put("a", 1);
+    assertEquals(on, toJsonNode(Collections.singletonMap("a", 1)));
+  }
+
+  @Test
+  public void testToObject() {
+    assertEquals(null, toObject(null));
+    assertEquals(JsonProperties.NULL_VALUE, toObject(NullNode.getInstance()));
+    assertEquals(true, toObject(BooleanNode.TRUE));
+    assertEquals(1, toObject(IntNode.valueOf(1)));
+    assertEquals(2L, toObject(IntNode.valueOf(2), Schema.create(Schema.Type.LONG)));
+    assertEquals(1.0f, toObject(DoubleNode.valueOf(1.0), Schema.create(Schema.Type.FLOAT)));
+    assertEquals(2.0, toObject(DoubleNode.valueOf(2.0)));
+    assertEquals(TextNode.valueOf("\u0001\u0002"), toJsonNode(new byte[]{1, 2}));
+    assertArrayEquals(new byte[]{1, 2},
+        (byte[]) toObject(TextNode.valueOf("\u0001\u0002"), Schema.create(Schema.Type.BYTES)));
+    assertEquals("a", toObject(TextNode.valueOf("a")));
+    assertEquals("UP", toObject(TextNode.valueOf("UP"),
+        SchemaBuilder.enumeration("Direction").symbols("UP", "DOWN")));
+
+    ArrayNode an = JsonNodeFactory.instance.arrayNode();
+    an.add(1);
+    assertEquals(Collections.singletonList(1), toObject(an));
+
+    ObjectNode on = JsonNodeFactory.instance.objectNode();
+    on.put("a", 1);
+    assertEquals(Collections.singletonMap("a", 1), toObject(on));
+    assertEquals(Collections.singletonMap("a", 1L), toObject(on,
+        SchemaBuilder.record("r").fields().requiredLong("a").endRecord()));
+
+    assertEquals(JsonProperties.NULL_VALUE, toObject(NullNode.getInstance(),
+        SchemaBuilder.unionOf().nullType().and().intType().endUnion()));
+
+    assertEquals("a", toObject(TextNode.valueOf("a"),
+        SchemaBuilder.unionOf().stringType().and().intType().endUnion()));
+  }
+
+}

Modified: avro/trunk/lang/java/ipc/src/test/java/org/apache/avro/TestProtocolGeneric.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/ipc/src/test/java/org/apache/avro/TestProtocolGeneric.java?rev=1640293&r1=1640292&r2=1640293&view=diff
==============================================================================
--- avro/trunk/lang/java/ipc/src/test/java/org/apache/avro/TestProtocolGeneric.java (original)
+++ avro/trunk/lang/java/ipc/src/test/java/org/apache/avro/TestProtocolGeneric.java Tue Nov 18 09:58:21 2014
@@ -44,8 +44,6 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Random;
 
-import org.codehaus.jackson.node.BooleanNode;
-
 public class TestProtocolGeneric {
   private static final Logger LOG
     = LoggerFactory.getLogger(TestProtocolGeneric.class);
@@ -222,7 +220,7 @@ public class TestProtocolGeneric {
     for (Field f : PROTOCOL.getType("TestRecord").getFields())
       fields.add(new Field(f.name(), f.schema(), null, null));
     fields.add(new Field("extra", Schema.create(Schema.Type.BOOLEAN),
-                         null, BooleanNode.TRUE));
+                         null, true));
     Schema record =
       Schema.createRecord("TestRecord", null, "org.apache.avro.test", false);
     record.setFields(fields);

Modified: avro/trunk/lang/java/ipc/src/test/java/org/apache/avro/TestSchema.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/ipc/src/test/java/org/apache/avro/TestSchema.java?rev=1640293&r1=1640292&r2=1640293&view=diff
==============================================================================
--- avro/trunk/lang/java/ipc/src/test/java/org/apache/avro/TestSchema.java (original)
+++ avro/trunk/lang/java/ipc/src/test/java/org/apache/avro/TestSchema.java Tue Nov 18 09:58:21 2014
@@ -819,21 +819,21 @@ public class TestSchema {
   }
 
   public static void checkBinaryJson(String json) throws Exception {
-    JsonNode node = Schema.parseJson(json);
+    Object node = Json.parseJson(json);
     ByteArrayOutputStream out = new ByteArrayOutputStream();
-    DatumWriter<JsonNode> writer = new Json.Writer();
+    DatumWriter<Object> writer = new Json.ObjectWriter();
     Encoder encoder = EncoderFactory.get().binaryEncoder(out, null);
     encoder = EncoderFactory.get().validatingEncoder(Json.SCHEMA, encoder);
     writer.write(node, encoder);
     encoder.flush();
     byte[] bytes = out.toByteArray();
 
-    DatumReader<JsonNode> reader = new Json.Reader();
+    DatumReader<Object> reader = new Json.ObjectReader();
     Decoder decoder = DecoderFactory.get().binaryDecoder(bytes, null);
     decoder = DecoderFactory.get().validatingDecoder(Json.SCHEMA, decoder);
-    JsonNode decoded = reader.read(null, decoder);
+    Object decoded = reader.read(null, decoder);
 
-    assertEquals("Decoded json does not match.", node.toString(), decoded.toString());
+    assertEquals("Decoded json does not match.", Json.toString(node), Json.toString(decoded));
   }
 
   private static final Schema ACTUAL =            // an empty record schema

Modified: avro/trunk/lang/java/mapred/src/test/java/org/apache/avro/mapred/TestGenericJob.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/mapred/src/test/java/org/apache/avro/mapred/TestGenericJob.java?rev=1640293&r1=1640292&r2=1640293&view=diff
==============================================================================
--- avro/trunk/lang/java/mapred/src/test/java/org/apache/avro/mapred/TestGenericJob.java (original)
+++ avro/trunk/lang/java/mapred/src/test/java/org/apache/avro/mapred/TestGenericJob.java Tue Nov 18 09:58:21 2014
@@ -47,7 +47,6 @@ import org.apache.hadoop.mapred.Mapper;
 import org.apache.hadoop.mapred.OutputCollector;
 import org.apache.hadoop.mapred.Reporter;
 import org.apache.hadoop.mapred.TextInputFormat;
-import org.codehaus.jackson.node.JsonNodeFactory;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -61,8 +60,7 @@ public class TestGenericJob {
     List<Field> fields = new ArrayList<Schema.Field>();
 
       
-    fields.add(new Field("Optional", createArraySchema(), "",
-                         JsonNodeFactory.instance.arrayNode()));
+    fields.add(new Field("Optional", createArraySchema(), "", new ArrayList<Object>()));
 
     Schema recordSchema =
       Schema.createRecord("Container", "", "org.apache.avro.mapred", false);
@@ -83,8 +81,7 @@ public class TestGenericJob {
   private static Schema createInnerSchema(String name) {
     Schema innerrecord = Schema.createRecord(name, "", "", false);
     innerrecord.setFields
-      (Arrays.asList(new Field(name, Schema.create(Type.LONG), "",
-                               JsonNodeFactory.instance.numberNode(0l))));
+      (Arrays.asList(new Field(name, Schema.create(Type.LONG), "", 0L)));
     return innerrecord;
   }
 

Modified: avro/trunk/lang/java/pom.xml
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/pom.xml?rev=1640293&r1=1640292&r2=1640293&view=diff
==============================================================================
--- avro/trunk/lang/java/pom.xml (original)
+++ avro/trunk/lang/java/pom.xml Tue Nov 18 09:58:21 2014
@@ -265,6 +265,7 @@
                 <version>${plugin-tools-javadoc.version}</version>
               </tagletArtifact>
             </tagletArtifacts>
+            <excludePackageNames>org.apache.avro.compiler.idl,*.internal</excludePackageNames>
           </configuration>
         </plugin>
         <plugin>

Modified: avro/trunk/lang/java/tools/src/main/java/org/apache/avro/tool/RpcReceiveTool.java
URL: http://svn.apache.org/viewvc/avro/trunk/lang/java/tools/src/main/java/org/apache/avro/tool/RpcReceiveTool.java?rev=1640293&r1=1640292&r2=1640293&view=diff
==============================================================================
--- avro/trunk/lang/java/tools/src/main/java/org/apache/avro/tool/RpcReceiveTool.java (original)
+++ avro/trunk/lang/java/tools/src/main/java/org/apache/avro/tool/RpcReceiveTool.java Tue Nov 18 09:58:21 2014
@@ -38,9 +38,6 @@ import org.apache.avro.io.JsonEncoder;
 import org.apache.avro.ipc.Ipc;
 import org.apache.avro.ipc.Server;
 import org.apache.avro.ipc.generic.GenericResponder;
-import org.codehaus.jackson.JsonEncoding;
-import org.codehaus.jackson.JsonFactory;
-import org.codehaus.jackson.JsonGenerator;
 
 /**
  * Receives one RPC call and responds.  (The moral equivalent
@@ -82,14 +79,11 @@ public class RpcReceiveTool implements T
       out.print(message.getName());
       out.print("\t");
       try {
-        JsonGenerator jsonGenerator = new JsonFactory().createJsonGenerator(
-            out, JsonEncoding.UTF8);
-        JsonEncoder jsonEncoder = EncoderFactory.get().jsonEncoder(message.getRequest(), jsonGenerator);
-
+        JsonEncoder jsonEncoder = EncoderFactory.get().jsonEncoder(message.getRequest(),
+            out);
         GenericDatumWriter<Object> writer = new GenericDatumWriter<Object>(
             message.getRequest());
         writer.write(request, jsonEncoder);
-        jsonGenerator.flush();
         jsonEncoder.flush();
         out.flush();
       } catch (IOException e) {