2011-06-10 1 views
23

J'utilise Jackson pour créer un objet JSON personnalisé. Est-ce la bonne façon de procéder?Meilleure façon d'utiliser Jackson JsonNodeFactory

Cela semble fonctionner correctement (et la sortie est correcte) mais il se peut que je manque la façon dont j'utilise JsonNodeFactory. L'objet est-il destiné à être passé comme je l'ai fait ici?

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

Répondre

36

Cela fonctionne, bien que l'intention est que c'est l'usine qui crée des instances. Mais le plus souvent vous suffit d'accéder tous à l'aide ObjectMapper, comme:

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

La raison principale de JsonNodeFactory séparée est de vous permettre de créer des types de noeuds personnalisés (généralement sous-classes d'instances standard); puis configurez ObjectMapper pour utiliser une fabrique différente. Par commodité, ArrayNode et ObjectNode font référence à une instance d'usine, qui est utilisée avec "putArray" et d'autres méthodes qui doivent créer de nouveaux nœuds.

3

Juste une suggestion, il serait plus facile de traiter directement avec les types de données simples et sérialisation ceux JSON et à l'arrière en utilisant Jackson ObjectMapper, plutôt que de traiter brut Jackson Treemodel

Donc, dans votre exemple, vous pouvez créer une structure du type:

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

class ARow{ 
    String ounces; 
    String revolutions; 
.. 

les commandes suivantes vont générer le JSON approprié pour vous:

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

Ce serait mieux et je l'ai fait dans certains cas. Le problème est, dans ce cas, j'ai besoin d'avoir le contrôle sur chaque ligne parce que j'ai des instructions conditionnelles sur quoi écrire. Parfois, les onces sont des grammes. Je dois écrire la couleur de la ligne sur chaque ligne. C'est différent pour chaque rangée. –

+0

@Drew H, je vous ai vu poster sur ce projet à quelques reprises. Dans l'ensemble, il me semble que peut-être il serait plus simple si vous avez fait moins ou pas de modifications basées sur la présentation de votre modèle objet au moment de la désérialisation, et simplement gonflé le modèle objet du JSON basé sur les données présentes dans le JSON, sans injecter de données supplémentaires, et plus tard, plus près dans le projet à l'endroit où les données doivent être affichées, avoir un code qui concerne la génération d'un modèle de vue (ou la modification du modèle existant) pour la présentation. –

+1

(continue ...Mon point est, s'il est possible de garder simple la liaison de données entre le JSON et les structures de données Java, alors gardez-le simple. C'est fantastique quand la désérialisation ne prend que deux ou trois lignes de code, ce qui est tout à fait possible et très courant quand on utilise des API comme Gson ou Jackson. Pour moi, c'est une raison majeure d'utiliser ces API. –

2

Si vous faites beaucoup de JsonNode bâtiment dans le code, vous pouvez être intéressant dans le jeu d'utilitaires suivant. L'avantage de les utiliser est qu'ils supportent un style de chaînage plus naturel qui montre mieux la structure du JSON en contruction.

Voici un exemple d'utilisation:

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

... 

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

ce qui équivaut à la JSON suivante:

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

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

    } 

} 

Notez que la mise en œuvre utilise Lombok , mais vous pouvez facilement le désosser pour remplir le passe-partout Java.

0
ObjectNode factory = JsonNodeFactory.instance.objectNode(); 

Cela fonctionne bien. Je pense que c'est un moyen plus facile.