2012-01-16 11 views
41

Sto pensando a qualcosa di simile:Come creare fluidamente JSON in Java?

String json = new JsonBuilder() 
    .add("key1", "value1") 
    .add("key2", "value2") 
    .add("key3", new JsonBuilder() 
    .add("innerKey1", "value3")) 
    .toJson(); 

Quali libreria Java JSON è migliore per questo tipo di edificio fluente?

Aggiornamento: ho avvolto GSON e ottenuto quasi il risultato desiderato ... with one hitch.

+0

Non penso di aver visto alcuna libreria JSON che segua quello stile. Forse potresti estendere una libreria esistente per fare ciò che vuoi? – aroth

+0

@aroth - Sto scrivendo un wrapper su com.google.gson mentre parliamo. – ripper234

+0

Quasi pronto - http://stackoverflow.com/questions/8876271/how-to-serialize-a-jsonobject-without-too-much-quotes – ripper234

risposta

54

Sto usando la biblioteca org.json e trovato ad essere bello e accogliente.

Esempio:

String jsonString = new JSONObject() 
        .put("JSON1", "Hello World!") 
        .put("JSON2", "Hello my World!") 
        .put("JSON3", new JSONObject() 
         .put("key1", "value1")).toString(); 

System.out.println(jsonString); 

USCITA:

{"JSON2":"Hello my World!","JSON3":{"key1":"value1"},"JSON1":"Hello World!"} 
+8

Questo non è molto fluido. – Vlad

+0

Il web che hai fornito non funziona più. Ti dispiacerebbe aggiornarlo? –

1

Sembra che probabilmente si desidera ottenere ahold di JSON-lib:

http://json-lib.sourceforge.net/

Douglas Crockford è il ragazzo che ha inventato JSON; la sua biblioteca Java è qui:

http://www.json.org/java/

Sembra che la gente a JSON-lib ripreso da dove Crockford lasciato. Entrambi supportano pienamente JSON, entrambi utilizzano (compatibili, per quanto posso dire) i costrutti JSONObject, JSONArray e JSONFunction.

'Speranza che aiuta ..

+0

Supporta la sintassi fluente? – ripper234

+0

Sì - Guarda qui: http://json-lib.sourceforge.net/snippets.html – paulsm4

9

Recentemente ho creato una libreria per la creazione GSON oggetti correntemente:

http://jglue.org/fluent-json/

funziona così:

JsonObject jsonObject = JsonBuilderFactory.buildObject() //Create a new builder for an object 
    .addNull("nullKey")       //1. Add a null to the object 

    .add("stringKey", "Hello")      //2. Add a string to the object 
    .add("stringNullKey", (String) null)   //3. Add a null string to the object 

    .add("numberKey", 2)       //4. Add a number to the object 
    .add("numberNullKey", (Float) null)   //5. Add a null number to the object 

    .add("booleanKey", true)      //6. Add a boolean to the object 
    .add("booleanNullKey", (Boolean) null)   //7. Add a null boolean to the object 

    .add("characterKey", 'c')      //8. Add a character to the object 
    .add("characterNullKey", (Character) null)  //9. Add a null character to the object 

    .addObject("objKey")       //10. Add a nested object 
    .add("nestedPropertyKey", 4)     //11. Add a nested property to the nested object 
    .end()          //12. End nested object and return to the parent builder 

    .addArray("arrayKey")       //13. Add an array to the object 
    .addObject()         //14. Add a nested object to the array 
     .end()          //15. End the nested object 
    .add("arrayElement")       //16. Add a string to the array 
    .end()          //17. End the array 

    .getJson();         //Get the JsonObject 

String json = jsonObject.toString(); 

E attraverso la magia dei generici genera errori di compilazione, se si tenta di aggiungere un elemento ad un array con una chiave di proprietà o di un elemento da un oggetto senza un nome di proprietà:

JsonObject jsonArray = JsonBuilderFactory.buildArray().addObject().end().add("foo", "bar").getJson(); //Error: tried to add a string with property key to array. 
JsonObject jsonObject = JsonBuilderFactory.buildObject().addArray().end().add("foo").getJson(); //Error: tried to add a string without property key to an object. 
JsonArray jsonArray = JsonBuilderFactory.buildObject().addArray("foo").getJson(); //Error: tried to assign an object to an array. 
JsonObject jsonObject = JsonBuilderFactory.buildArray().addObject().getJson(); //Error: tried to assign an object to an array. 

Infine c'è un supporto per la mappatura nell'API che ti permette di mappare i tuoi oggetti di dominio su JSON. L'obiettivo è quando Java8 verrà rilasciato, quindi sarà possibile fare qualcosa del genere:

Collection<User> users = ...; 
JsonArray jsonArray = JsonBuilderFactory.buildArray(users, { u-> buildObject() 
                   .add("userName", u.getName()) 
                   .add("ageInYears", u.getAge()) }) 
                   .getJson(); 
0

L'implementazione di riferimento su json.org include un'interfaccia fluente. Controlla JSONWriter e la sottoclasse di implementazione toString JSONStringer

61

Vedere Java Json specification. Questa è la strada giusta:

String json = Json.createObjectBuilder() 
      .add("key1", "value1") 
      .add("key2", "value2") 
      .build() 
      .toString(); 
+7

Questa dovrebbe essere contrassegnata come risposta corretta nel 2015 poiché questo fa parte di 'javax.json' in Java 7 e versioni successive. –

+19

È Java EE API, non Java SE. – igorp1024

+0

Qualche idea su come creare un oggetto JsonString da un oggetto String nell'API javax.json? – Raymond

2
String json = new JsonBuilder(new GsonAdapter()) 
    .object("key1", "value1") 
    .object("key2", "value2") 
    .object("key3") 
    .object("innerKey1", "value3") 
    .build().toString(); 

Se si pensa che la soluzione di cui sopra è elegante, quindi si prega di provare la mia JsonBuilder lib. È stato creato per consentire un modo di costruire strutture JSON per molti tipi di librerie Json. Attuali implementazioni includono Gson, Jackson e MongoDB. Per esempio.Jackson basta scambiare:

String json = new JsonBuilder(new JacksonAdapter()). 

sarò felicemente aggiungerne altri a richiesta, `s anche abbastanza facile da implementare uno per se stessi.

2

Se si utilizza Jackson, fare un gran numero di JsonNode in codice, potrebbe essere interessante il seguente set di utilità. Il vantaggio di usarli è che supportano uno stile di concatenamento più naturale che mostra meglio la struttura del JSON in costruzione.

Ecco un esempio di utilizzo:

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

... 

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

che è equivalente al seguente JSON:

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

Qui ci sono le classi:

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

    } 

} 

Nota che l'applicazione utilizza Lombok , ma puoi facilmente desuggerlo per compilare la piastra di Java.

0

è molto più facile di quanto si pensi per scrivere il proprio, basta usare un'interfaccia per JsonElementInterface con un metodo string toJson(), e una classe astratta AbstractJsonElement attuazione di tale interfaccia,

allora tutto ciò che dovete fare è avere una classe per JSONProperty che implementa l'interfaccia, e JSONValue (qualsiasi token), JSONArray ([...]), e JSONObject ({...}) che estendono la classe astratta

JSONObject ha una lista di JSONProperty s'
JSONArray ha un li st di AbstractJsonElement s'

la funzione aggiuntiva in ogni dovrebbe prendere una lista vararg di quel tipo, e tornare this

ora, se non ti piace qualcosa che si può semplicemente modificarlo

la benifit di l'intefaccia e la classe astratta è che JSONArray non può accettare proprietà, ma JSONProperty può accettare oggetti o matrici