Как свободно создавать JSON на Java?
Я думаю о чем-то вроде:
String json = new JsonBuilder()
.add("key1", "value1")
.add("key2", "value2")
.add("key3", new JsonBuilder()
.add("innerKey1", "value3"))
.toJson();
Какая библиотека Java JSON лучше всего подходит для этого свободного здания?
Обновление. Я завернул GSON и получил практически нужный результат... с одним зацеплением.
Ответы
Ответ 1
Я использую библиотеку org.json и нашел ее приятной и дружелюбной.
Пример:
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);
ВЫВОД:
{"JSON2":"Hello my World!","JSON3":{"key1":"value1"},"JSON1":"Hello World!"}
Ответ 2
См. спецификацию Java Json.
Это правильный путь:
String json = Json.createObjectBuilder()
.add("key1", "value1")
.add("key2", "value2")
.build()
.toString();
Ответ 3
Недавно я создал библиотеку для создания объектов Gson:
http://jglue.org/fluent-json/
Он работает следующим образом:
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();
И благодаря магии генериков генерирует ошибки компиляции, если вы пытаетесь добавить элемент в массив с ключом свойства или элементом для объекта без имени свойства:
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.
Наконец, в API есть поддержка отображения, которая позволяет вам сопоставлять объекты вашего домена с JSON. Целью, когда Java8 будет выпущен, вы сможете сделать что-то вроде этого:
Collection<User> users = ...;
JsonArray jsonArray = JsonBuilderFactory.buildArray(users, { u-> buildObject()
.add("userName", u.getName())
.add("ageInYears", u.getAge()) })
.getJson();
Ответ 4
Если вы используете Джексона для создания 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.
Ответ 5
String json = new JsonBuilder(new GsonAdapter())
.object("key1", "value1")
.object("key2", "value2")
.object("key3")
.object("innerKey1", "value3")
.build().toString();
Если вы считаете, что вышеупомянутое решение изящно, попробуйте, пожалуйста, JsonBuilder lib. Он был создан, чтобы позволить один способ построения json-структур для многих типов библиотек Json. Текущие реализации включают Gson, Jackson и MongoDB. То есть. Джексон просто поменяет:
String json = new JsonBuilder(new JacksonAdapter()).
Я с радостью добавлю другие по запросу, также очень легко реализовать один из себя.
Ответ 6
Похоже, вы, вероятно, захотите получить json-lib:
http://json-lib.sourceforge.net/
Дуглас Крокфорд - тот парень, который изобрел JSON; его библиотека Java находится здесь:
http://www.json.org/java/
Похоже, что люди в json-lib собрались там, где остановился Крокфорд. Оба полностью поддерживают JSON, и используют (совместимые, насколько я могу судить) конструкции JSONObject, JSONArray и JSONFunction.
'Надеюсь, что это поможет.
Ответ 7
Ссылочная реализация на json.org включает свободный интерфейс. Проверьте JSONWriter и его подкласс, реализующий toString, JSONStringer
Ответ 8
это намного проще, чем вы думаете, чтобы написать свой собственный, просто используйте интерфейс для JsonElementInterface
с помощью метода string toJson()
и абстрактный класс AbstractJsonElement
, реализующий этот интерфейс,
тогда все, что вам нужно сделать, это иметь класс для JSONProperty
, который реализует интерфейс, и JSONValue
(любой токен), JSONArray
([...]) и JSONObject
({...}), которые расширяют абстрактный класс
JSONObject
имеет список JSONProperty
JSONArray
имеет список AbstractJsonElement
's
ваша функция добавления в каждом из них должна взять список vararg этого типа и вернуть this
теперь, если вам не нравится что-то, вы можете просто настроить его
полезность inteface и абстрактного класса заключается в том, что JSONArray
не может принимать свойства, но JSONProperty
может принимать объекты или массивы