Подтвердить что ты не робот

Лучший способ использования Jackson JsonNodeFactory

Я использую Jackson для создания пользовательского объекта JSON. Правильно ли это можно сделать?

Кажется, что он работает хорошо (и выход правильный), но мне может не хватать, как я использую JsonNodeFactory. Является ли объект переданным, как я здесь сделал?

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);
4b9b3361

Ответ 1

Это работает, хотя намерение заключается в том, что он factory создает экземпляры. Но чаще всего вы просто получаете доступ ко всему, используя ObjectMapper, например:

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

Основной причиной отдельного JsonNodeFactory является создание пользовательских типов node (обычно подклассов стандартных экземпляров); а затем настройте ObjectMapper для использования разных factory. Для удобства ArrayNode и ObjectNode имеют ссылку на экземпляр factory, который используется с "putArray" и другими методами, которые должны создавать новые узлы.

Ответ 2

Просто предложение, было бы проще напрямую разобраться с простыми типами данных и сериализовать их для JSON и обратно с помощью Jackson ObjectMapper, вместо того, чтобы иметь дело с raw Jackson Treemodel

Итак, в вашем примере вы можете создать структуру следующего типа:

class AaData{
    private List<ARow> rowList = new ArrayList<ARow>();
..

class ARow{
    String ounces;
    String revolutions;
..

Затем следующее создаст для вас соответствующий json:

StringWriter sw = new StringWriter();
JsonFactory jf = new JsonFactory();
ObjectMapper m = new ObjectMapper();
m.writeValue(sw, aaData);
System.out.println(sw.toString());

Ответ 3

Если вы выполняете много кода JsonNode в коде, вы можете быть интересны в следующем наборе утилит. Преимущество их использования заключается в том, что они поддерживают более естественный стиль цепочки, который лучше показывает структуру JSON в рамках проекта.

Вот пример использования:

import static JsonNodeBuilders.array;
import static JsonNodeBuilders.object;

...

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

Это эквивалентно следующему JSON:

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

Вот классы:

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;
    }

  }

}

Обратите внимание, что в реализации используется Lombok, но вы можете легко удалить ее, чтобы заполнить шаблон Java.