Bagaimana cara membangun JSON dengan lancar di Java?

107

Saya sedang memikirkan sesuatu seperti:

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

Library Java JSON manakah yang terbaik untuk jenis bangunan yang lancar?

Pembaruan : Saya membungkus GSON dan mendapatkan hasil yang hampir diinginkan ... dengan satu halangan .

ripper234
sumber
1
Saya rasa saya belum pernah melihat perpustakaan JSON yang mengikuti gaya itu. Mungkin Anda bisa memperluas perpustakaan yang ada untuk melakukan apa yang Anda inginkan?
Apakah
1
@aroth - Saya sedang menulis pembungkus seputar com.google.gson saat kita berbicara.
ripper234
1
Hampir siap - stackoverflow.com/questions/8876271/…
ripper234
1
Buat "sarang" dari Peta dan Daftar yang sesuai dan buat serialisasi. Hindari pernyataan "polimer rantai panjang".
Hot Licks

Jawaban:

141

Saya menggunakan pustaka org.json dan merasa pustaka itu bagus dan ramah.

Contoh:

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

KELUARAN:

{"JSON2":"Hello my World!","JSON3":{"key1":"value1"},"JSON1":"Hello World!"}
dku.rajkumar
sumber
15
Ini tidak terlalu lancar.
Vlad
Web yang Anda berikan tidak berfungsi lagi. Maukah Anda memperbaruinya?
Saša Zejnilović
13
@ Vlad - persis seperti yang disarankan oleh pembuat bangunan yang fasih kepada saya. Dapatkah Anda memberikan contoh penyiapan yang menurut Anda lebih baik?
scubbo
3
Ini masih merupakan opsi yang lebih bersih. Konyol bahwa pengembang Java masih harus berhenti sejenak untuk mencari opsi terbaik untuk parse / build JSON pada tahun 2020.
mtyson
113

Lihat spesifikasi Java EE 7 Json . Ini cara yang benar:

String json = Json.createObjectBuilder()
            .add("key1", "value1")
            .add("key2", "value2")
            .build()
            .toString();
Yumarx Polanco
sumber
8
Ini harus ditandai sebagai jawaban yang benar pada tahun 2015 karena ini adalah bagian dari javax.jsonJava 7 dan yang lebih baru.
Sridhar Sarnobat
42
Ini adalah Java EE API, bukan Java SE.
igorp1024
Ada ide bagaimana membuat objek JsonString dari objek String di javax.json API?
Raymond
4
ketergantungan maven: mvnrepository.com/artifact/javax/javaee-api/7.0
ankitkpd
12
Ketergantungan Maven untuk satu-satunya javax.jsonpaket adalah yang ini
JeanValjean
12

Saya baru-baru ini membuat perpustakaan untuk membuat objek Gson dengan lancar:

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

Ini bekerja seperti ini:

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

Dan melalui keajaiban generik, ini menghasilkan kesalahan kompilasi jika Anda mencoba menambahkan elemen ke array dengan kunci properti atau elemen ke objek tanpa nama properti:

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.

Terakhir, ada dukungan pemetaan di API yang memungkinkan Anda memetakan objek domain Anda ke JSON. Tujuannya adalah saat Java8 dirilis, Anda akan dapat melakukan sesuatu seperti ini:

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

Jika Anda menggunakan Jackson untuk melakukan banyak JsonNodepembangunan dalam kode, Anda mungkin tertarik pada rangkaian utilitas berikut. Manfaat menggunakannya adalah bahwa mereka mendukung gaya perangkaian yang lebih alami yang menunjukkan struktur JSON yang sedang dibangun dengan lebih baik.

Berikut ini contoh penggunaan:

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

...

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

Yang setara dengan JSON berikut:

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

Berikut kelasnya:

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

  }

}

Perhatikan bahwa implementasinya menggunakan Lombok , tetapi Anda dapat dengan mudah mendesainnya untuk mengisi boilerplate Java.

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

Jika menurut Anda solusi di atas elegan, silakan coba lib JsonBuilder saya . Itu dibuat untuk memungkinkan satu cara membangun struktur json untuk banyak jenis perpustakaan Json. Implementasi saat ini termasuk Gson, Jackson dan MongoDB. Untuk mis. Jackson baru saja bertukar:

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

Saya akan dengan senang hati menambahkan orang lain berdasarkan permintaan, ini juga cukup mudah untuk diterapkan satu per satu.

Homyk
sumber
sayangnya tidak di pusat maven saat ini, lihat github.com/HknL/JsonBuilder/issues/8
dschulten
1

Sepertinya Anda mungkin ingin mendapatkan json-lib:

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

Douglas Crockford adalah orang yang menemukan JSON; perpustakaan Java-nya ada di sini:

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

Kedengarannya seperti orang-orang di json-lib mengambil tempat yang ditinggalkan Crockford. Keduanya sepenuhnya mendukung JSON, keduanya menggunakan (kompatibel, sejauh yang saya tahu) konstruksi JSONObject, JSONArray dan JSONFunction.

'Semoga itu bisa membantu ..

paulsm4
sumber
Apakah itu mendukung sintaks yang lancar?
ripper234
0

jauh lebih mudah daripada yang Anda pikirkan untuk menulis sendiri, cukup gunakan antarmuka JsonElementInterfacedengan metode string toJson(), dan kelas abstrak yang AbstractJsonElementmengimplementasikan antarmuka itu,

maka yang harus Anda lakukan adalah memiliki kelas JSONPropertyyang mengimplementasikan antarmuka, dan JSONValue(token apa pun), JSONArray([...]), dan JSONObject({...}) yang memperluas kelas abstrak

JSONObjectmemiliki daftar JSONProperty's
JSONArraymemiliki daftar AbstractJsonElement' s

fungsi add Anda di masing-masing harus mengambil daftar vararg jenis itu, dan kembali this

sekarang jika Anda tidak menyukai sesuatu, Anda dapat mengubahnya

Manfaat dari inteface dan kelas abstrak adalah JSONArraytidak dapat menerima properti, tetapi JSONPropertydapat menerima objek atau array

Austin_Anderson
sumber