Java'da JSON'u akıcı bir şekilde nasıl oluşturabilirim?


107

Şöyle bir şey düşünüyorum:

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

Bu tür akıcı bina için hangi Java JSON kitaplığı en iyisidir?

Güncelleme : GSON'u tamamladım ve neredeyse istenen sonucu elde ettim ... tek bir aksaklıkla .


1
Bu stili takip eden herhangi bir JSON kütüphanesi gördüğümü sanmıyorum. Belki istediğinizi yapmak için mevcut bir kütüphaneyi genişletebilirsiniz?
aroth

1
@aroth - Biz konuşurken com.google.gson etrafında bir sarmalayıcı yazıyorum.
ripper234


1
Haritalar ve Listelerin uygun "yuvasını" oluşturun ve seri hale getirin. "Uzun zincirli polimer" ifadelerinden kaçının.
Hot Licks

Yanıtlar:


141

Org.json kütüphanesini kullanıyorum ve hoş ve arkadaşça buldum.

Misal:

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

ÇIKTI:

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

15
Bu pek akıcı değil.
Vlad

Sağladığınız web artık çalışmıyor. Güncellemek ister misiniz?
Saša Zejnilović

13
@Vlad - Bu tam olarak akıcı inşaatçıların bana önerdiği şey. Daha iyi olduğunu düşündüğünüz bir kurulum örneği verebilir misiniz?
scubbo

3
Bu hala daha temiz bir seçenektir. Java geliştiricilerinin 2020'de JSON ayrıştırma / derleme için en iyi seçeneği bulmak için hala duraklaması
gerekmesi gülünç

113

Bkz Java EE 7 Json şartname . Doğru yol bu:

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

8
Bu javax.json, Java 7 ve sonraki sürümlerin bir parçası olduğu için 2015'te doğru yanıt olarak işaretlenmelidir .
Sridhar Sarnobat

42
Java SE değil, Java EE API'dir.
igorp1024

Javax.json API'sinde bir String nesnesinden bir JsonString nesnesinin nasıl oluşturulacağı hakkında bir fikriniz var mı?
Raymond


12
Maven bağımlılık tek için javax.jsonpaketin olan bu bir
Jean Valjean

12

Yakın zamanda Gson nesnelerini akıcı bir şekilde oluşturmak için bir kitaplık oluşturdum:

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

Şu şekilde çalışır:

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

Ve bir özellik anahtarına sahip bir diziye bir öğe veya özellik adı olmayan bir nesneye bir öğe eklemeye çalışırsanız, jeneriklerin büyüsü yoluyla derleme hataları üretir:

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.

Son olarak, API'de etki alanı nesnelerinizi JSON ile eşlemenizi sağlayan eşleme desteği vardır. Hedef, Java8 yayınlandığında şöyle bir şey yapabileceksiniz:

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

8

Jackson'ı JsonNodekodda çok fazla bina kullanıyorsanız , aşağıdaki yardımcı programlarla ilgilenebilirsiniz. Bunları kullanmanın yararı, yapım aşamasında olan JSON'un yapısını daha iyi gösteren daha doğal bir zincirleme stilini desteklemeleri.

İşte örnek bir kullanım:

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

...

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

Aşağıdaki JSON ile eşdeğer olan:

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

İşte sınıflar:

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

  }

}

Uygulamanın Lombok kullandığına dikkat edin , ancak Java standart metnini doldurmak için kolayca tasarlayabilirsiniz.


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

Yukarıdaki çözümün zarif olduğunu düşünüyorsanız, lütfen JsonBuilder kitaplığımı deneyin . Birçok Json kitaplığı türü için json yapıları oluşturmanın tek bir yolunu sağlamak için oluşturulmuştur. Mevcut uygulamalar arasında Gson, Jackson ve MongoDB bulunmaktadır. İe için. Jackson sadece değiş tokuş:

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

İstek üzerine memnuniyetle başkalarını ekleyeceğim, tek tek uygulamak da oldukça kolay.


ne yazık ki şu anda maven merkezinde değil, bkz. github.com/HknL/JsonBuilder/issues/8
dschulten

1

Muhtemelen json-lib'e ulaşmak istiyor gibisin:

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

Douglas Crockford, JSON'u icat eden kişidir; Java kitaplığı burada:

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

Görünüşe göre json-lib'deki insanlar Crockford'un bıraktığı yerden devam ettiler. Her ikisi de JSON'u tam olarak destekliyor, her ikisi de JSONObject, JSONArray ve JSONFunction yapılarını kullanıyor (anlayabildiğim kadarıyla uyumlu).

'Umarım yardımcı olur ..


Akıcı sözdizimini destekliyor mu?
ripper234


0

kendi yazmanızı düşündüğünüzden çok daha kolay, sadece JsonElementInterfacebir yöntem için bir arayüz string toJson()ve AbstractJsonElementbu arayüzü uygulayan soyut bir sınıf kullanın ,

o zaman yapmanız gereken tek şey, JSONPropertyarayüzü uygulayan bir sınıfa ve soyut sınıfı genişleten JSONValue(herhangi bir simge), JSONArray([...]) ve JSONObject({...})

JSONObjectbir listesi vardır JSONProperty'ın
JSONArraybir listesi vardır AbstractJsonElements'

her birindeki ekleme işleviniz bu türden bir vararg listesi almalı ve this

şimdi bir şeyi beğenmezsen ince ayar yapabilirsin

arayüzün ve soyut sınıfın faydası, JSONArrayözellikleri kabul edemeyen, ancak JSONPropertynesneleri veya dizileri kabul edebilmesidir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.