2012-01-16 9 views
41

Estoy pensando en algo como:¿Cómo construir con fluidez JSON en Java?

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

Qué biblioteca de Java JSON es mejor para este tipo de edificio con fluidez?

Actualización: Envolví GSON y obtuve casi el resultado deseado ... with one hitch.

+0

No creo que haya visto ninguna biblioteca JSON que siga ese estilo. ¿Tal vez podría ampliar una biblioteca existente para hacer lo que quiere? – aroth

+0

@aroth: estoy escribiendo un resumen sobre com.google.gson mientras hablamos. – ripper234

+0

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

Respuesta

54

estoy usando la biblioteca org.json y nos pareció ser agradable y amable.

Ejemplo:

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

SALIDA:

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

Esto no es muy fluido. – Vlad

+0

La web que proporcionó ya no funciona. ¿Te importaría actualizarlo? –

1

que suena es probable que desee ponerme en contacto con la biblioteca JSON:

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

Douglas Crockford es el tipo que inventó JSON; su biblioteca de Java está aquí:

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

Parece que la gente de la biblioteca JSON recogió donde Crockford dejó. Ambos soportan completamente JSON, ambos utilizan construcciones JSONObject, JSONArray y JSONFunction (compatibles, hasta donde puedo decir).

'Espero que ayude ..

+0

¿Es compatible con la sintaxis fluida? – ripper234

+0

Sí - Mire aquí: http://json-lib.sourceforge.net/snippets.html – paulsm4

9

recientemente he creado una librería para crear Gson objetos con fluidez:

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

funciona así:

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

Y a través de la magia de los genéricos que genera errores de compilación si se intenta agregar un elemento a un conjunto con una clave de propiedad o un elemento a un objeto sin un nombre de propiedad:

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. 

último hay soporte de mapeo en la API que le permite mapear los objetos de su dominio a JSON. El objetivo es cuando se libere Java8 y podrá hacer algo como esto:

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

Vea el Java Json specification. Esta es la forma correcta:

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

Esto debería marcarse como la respuesta correcta en 2015, ya que es parte de 'javax.json' en Java 7 y posterior. –

+19

Es API de Java EE, no Java SE. – igorp1024

+0

¿Alguna idea de cómo crear un objeto JsonString a partir de un objeto String en la API javax.json? – Raymond

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

Si cree que la solución anterior es elegante, a continuación, por favor probar mi JsonBuilder lib. Fue creado para permitir una forma de construir estructuras json para muchos tipos de bibliotecas Json. Las implementaciones actuales incluyen Gson, Jackson y MongoDB. Por ejemplo.Jackson sólo cambio:

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

voy felizmente añadir otros a petición, `s también bastante fácil de implementar uno por uno mismo.

2

Si está usando Jackson para hacer un montón de código JsonNode, puede ser interesante en el siguiente conjunto de utilidades. El beneficio de usarlos es que admiten un estilo de encadenamiento más natural que muestra mejor la estructura del JSON en construcción.

Aquí es un ejemplo de uso:

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

... 

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

que es equivalente a la siguiente JSON:

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

Estas son las clases:

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

    } 

} 

Tenga en cuenta que la aplicación utiliza Lombok , pero puede desaguarlo fácilmente para completar el texto estándar de Java.

0

Es mucho más fácil de lo que piensa para escribir su propia, sólo tiene que utilizar una interfaz para JsonElementInterface con un método string toJson(), y una clase abstracta AbstractJsonElement aplicación de dicha interfaz,

entonces todo lo que tiene que hacer es tener una clase para JSONProperty que implementa la interfaz, y JSONValue (cualquier token), JSONArray ([...]), y JSONObject ({...}) que se extienden a la clase abstracta

JSONObject tiene una lista de JSONProperty 's
JSONArray tiene un li st de AbstractJsonElement 's

su función de complemento en cada uno debe tener una lista vararg de ese tipo, y volver this

ahora si no te gusta algo que sólo puede modificarlo

el beneficio de un la interfaz y la clase abstracta es que JSONArray no puede aceptar propiedades, pero JSONProperty puede aceptar objetos o matrices

Cuestiones relacionadas