Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to use Jackson JsonNodeFactory

I'm using Jackson to build a custom JSON object. Is the correct way of going about this?

It seems to work well (and the output is correct) but I may be missing the way I use JsonNodeFactory. Is the object meant to be passed around like I have done here?

JsonNodeFactory factory = JsonNodeFactory.instance; ObjectNode dataTable = new ObjectNode(factory); ArrayNode aaData = new ArrayNode(factory);  for (PkgLoad pkgLoad : pkgLoadList) {     ObjectNode row = new ObjectNode(factory);     row.put("ounces", pkgLoad.ounces);     row.put("revolutions", pkgLoad.revolutions);     aaData.add(row); }  dataTable.put("aaData", aaData); 
like image 800
Drew H Avatar asked Jun 10 '11 20:06

Drew H


People also ask

What is difference between JsonNode and Jsonobject?

ObjectNode is a concrete implementation of JsonNode that maps a JSON object, and a JSON object is defined as following: An object is an unordered set of name/value pairs.

What is JsonNodeFactory?

public class JsonNodeFactory extends Object implements Serializable, JsonNodeCreator. Base class that specifies methods for getting access to Node instances (newly constructed, or shared, depending on type), as well as basic implementation of the methods.

What is the difference between JsonNode and ObjectNode?

JsonNode represents any valid Json structure whereas ObjectNode and ArrayNode are particular implementations for objects (aka maps) and arrays, respectively.


2 Answers

This works, although intention is that it's factory that creates instances. But most commonly you just access all of it using ObjectMapper, like:

ObjectMapper mapper = new ObjectMapper(); ObjectNode dataTable = mapper.createObjectNode(); ArrayNode aa = dataTable.putArray("aaData"); 

The main reason for separate JsonNodeFactory is to allow you to create custom node types (usually sub-classes of standard instances); and then configure ObjectMapper to use different factory. For convenience, ArrayNode and ObjectNode do have reference to a factory instance, which is used with "putArray" and other methods that need to create new nodes.

like image 106
StaxMan Avatar answered Sep 20 '22 07:09

StaxMan


If you do a lot of JsonNode building in code, you may be interesting in the following set of utilities. The benefit of using them is that they support a more natural chaining style that better shows the structure of the JSON under contruction.

Here is an example usage:

import static JsonNodeBuilders.array; import static JsonNodeBuilders.object;  ...  val request = object("x", "1").with("y", array(object("z", "2"))).end(); 

Which is equivalent to the following JSON:

{"x":"1", "y": [{"z": "2"}]} 

Here are the classes:

import static lombok.AccessLevel.PRIVATE;  import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode;  import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.val;  /**  * Convenience {@link JsonNode} builder.  */ @NoArgsConstructor(access = PRIVATE) public final class JsonNodeBuilders {    /**    * Factory methods for an {@link ObjectNode} builder.    */    public static ObjectNodeBuilder object() {     return object(JsonNodeFactory.instance);   }    public static ObjectNodeBuilder object(@NonNull String k1, boolean v1) {     return object().with(k1, v1);   }    public static ObjectNodeBuilder object(@NonNull String k1, int v1) {     return object().with(k1, v1);   }    public static ObjectNodeBuilder object(@NonNull String k1, float v1) {     return object().with(k1, v1);   }    public static ObjectNodeBuilder object(@NonNull String k1, String v1) {     return object().with(k1, v1);   }    public static ObjectNodeBuilder object(@NonNull String k1, String v1, @NonNull String k2, String v2) {     return object(k1, v1).with(k2, v2);   }    public static ObjectNodeBuilder object(@NonNull String k1, String v1, @NonNull String k2, String v2,       @NonNull String k3, String v3) {     return object(k1, v1, k2, v2).with(k3, v3);   }    public static ObjectNodeBuilder object(@NonNull String k1, JsonNodeBuilder<?> builder) {     return object().with(k1, builder);   }    public static ObjectNodeBuilder object(JsonNodeFactory factory) {     return new ObjectNodeBuilder(factory);   }    /**    * Factory methods for an {@link ArrayNode} builder.    */    public static ArrayNodeBuilder array() {     return array(JsonNodeFactory.instance);   }    public static ArrayNodeBuilder array(@NonNull boolean... values) {     return array().with(values);   }    public static ArrayNodeBuilder array(@NonNull int... values) {     return array().with(values);   }    public static ArrayNodeBuilder array(@NonNull String... values) {     return array().with(values);   }    public static ArrayNodeBuilder array(@NonNull JsonNodeBuilder<?>... builders) {     return array().with(builders);   }    public static ArrayNodeBuilder array(JsonNodeFactory factory) {     return new ArrayNodeBuilder(factory);   }    public interface JsonNodeBuilder<T extends JsonNode> {      /**      * Construct and return the {@link JsonNode} instance.      */     T end();    }    @RequiredArgsConstructor   private static abstract class AbstractNodeBuilder<T extends JsonNode> implements JsonNodeBuilder<T> {      /**      * The source of values.      */     @NonNull     protected final JsonNodeFactory factory;      /**      * The value under construction.      */     @NonNull     protected final T node;      /**      * Returns a valid JSON string, so long as {@code POJONode}s not used.      */     @Override     public String toString() {       return node.toString();     }    }    public final static class ObjectNodeBuilder extends AbstractNodeBuilder<ObjectNode> {      private ObjectNodeBuilder(JsonNodeFactory factory) {       super(factory, factory.objectNode());     }      public ObjectNodeBuilder withNull(@NonNull String field) {       return with(field, factory.nullNode());     }      public ObjectNodeBuilder with(@NonNull String field, int value) {       return with(field, factory.numberNode(value));     }      public ObjectNodeBuilder with(@NonNull String field, float value) {       return with(field, factory.numberNode(value));     }      public ObjectNodeBuilder with(@NonNull String field, boolean value) {       return with(field, factory.booleanNode(value));     }      public ObjectNodeBuilder with(@NonNull String field, String value) {       return with(field, factory.textNode(value));     }      public ObjectNodeBuilder with(@NonNull String field, JsonNode value) {       node.set(field, value);       return this;     }      public ObjectNodeBuilder with(@NonNull String field, @NonNull JsonNodeBuilder<?> builder) {       return with(field, builder.end());     }      public ObjectNodeBuilder withPOJO(@NonNull String field, @NonNull Object pojo) {       return with(field, factory.pojoNode(pojo));     }      @Override     public ObjectNode end() {       return node;     }    }    public final static class ArrayNodeBuilder extends AbstractNodeBuilder<ArrayNode> {      private ArrayNodeBuilder(JsonNodeFactory factory) {       super(factory, factory.arrayNode());     }      public ArrayNodeBuilder with(boolean value) {       node.add(value);       return this;     }      public ArrayNodeBuilder with(@NonNull boolean... values) {       for (val value : values)         with(value);       return this;     }      public ArrayNodeBuilder with(int value) {       node.add(value);       return this;     }      public ArrayNodeBuilder with(@NonNull int... values) {       for (val value : values)         with(value);       return this;     }      public ArrayNodeBuilder with(float value) {       node.add(value);       return this;     }      public ArrayNodeBuilder with(String value) {       node.add(value);       return this;     }      public ArrayNodeBuilder with(@NonNull String... values) {       for (val value : values)         with(value);       return this;     }      public ArrayNodeBuilder with(@NonNull Iterable<String> values) {       for (val value : values)         with(value);       return this;     }      public ArrayNodeBuilder with(JsonNode value) {       node.add(value);       return this;     }      public ArrayNodeBuilder with(@NonNull JsonNode... values) {       for (val value : values)         with(value);       return this;     }      public ArrayNodeBuilder with(JsonNodeBuilder<?> value) {       return with(value.end());     }      public ArrayNodeBuilder with(@NonNull JsonNodeBuilder<?>... builders) {       for (val builder : builders)         with(builder);       return this;     }      @Override     public ArrayNode end() {       return node;     }    }  } 

Note that the implementation uses Lombok, but you can easily desugar it to fill in the Java boilerplate.

like image 37
btiernay Avatar answered Sep 21 '22 07:09

btiernay