Best way to use Jackson JsonNodeFactory

前端 未结 4 410
北恋
北恋 2021-01-30 22:34

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

4条回答
  •  挽巷
    挽巷 (楼主)
    2021-01-30 22:46

    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 {
    
        /**
         * Construct and return the {@link JsonNode} instance.
         */
        T end();
    
      }
    
      @RequiredArgsConstructor
      private static abstract class AbstractNodeBuilder implements JsonNodeBuilder {
    
        /**
         * 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 {
    
        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 {
    
        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 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.

提交回复
热议问题