Как использовать "JSR-353: Java API для обработки JSON" без цепочки методов

Я хотел поделиться своим вопросом / ответом с использованием нового JSR-353, который является Java API для JSON Processing. В частности, вы можете манипулировать данными JSON в двух разных "API" - потоковом и объектном API.

Если вы введете "gsr-353 tutorial" в Google, вы получите много результатов.

https://jcp.org/en/jsr/detail?id=353 ~ подробности по конкретному запросу.

https://jsonp.java.net/ ~ основной сайт для API, также содержит ссылку на учебник Oracle в разделе "документация", расположенном здесь https://docs.oracle.com/javaee/7/tutorial/doc/jsonp.htm Я расскажу об этом уроке позже.

и, наконец, этот

http://www.javabeat.net/java-json-api-jsr-353/

Сначала я хочу поговорить о последней ссылке, так как она дала мне много хороших подробностей и является одним из немногих реальных учебных пособий (есть и другие, но в основном они одинаковые).

То, что я действительно пытался узнать об API, будучи новичком не только в этом API, но и в JSON в целом, так это.

Когда использовать потоковый API и объектную модель API?

Если вы хотите, чтобы данные JSON были записаны в символьный поток, например в файл, или в байтовый поток, то потоковый API будет лучшим выбором, поскольку он непосредственно выполняет операцию записи в буфер, не создавая дерево объектов в памяти, т.е. не является промежуточной формой, созданной до создания окончательных данных JSON.

Если вы хотите хранить данные JSON как дерево объектов в памяти, т.е. не записывать данные в какой-либо поток, а хранить дерево в памяти, чтобы можно было повторно использовать данные JSON без повторной обработки или можно также сериализовать дерево объектов в сохранить / сохранить данные JSON. Здесь данные JSON будут представлены в виде дерева объектов.

Теперь описание API потоковой передачи имело для меня большой смысл, и мне нужно было сохранить файл, так что для меня это имело смысл.

Что касается Object API, то также имело смысл то, что он делал, сохранил объект, чтобы я мог использовать его позже в своем коде, потрясающе.

Проблема в том, что я не получил ответ на свой вопрос, который я объясню, что именно я сейчас ищу.

Мой вопрос:

У меня в основном есть 1 объект, который содержит другие объекты / массивы.

Первоначально я использовал BufferedWriter для записи данных в новую строку в текстовый файл.

мой формат выглядит примерно так

bw.write(1);
bw.newLine();
bw.write(2);
bw.newLine();

for(int i = 0; i < 4; i++)
{
bw.write(i);
bw.newLine();
}

bw.write(2);
bw.newLine();

for(int j = 0; j < 2; j++)
{
bw.write(j);
bw.newLine();
bw.write(j+5);
bw.newLine();
bw.write(2);
bw.newLine();
bw.write(j*4);
bw.newLine();
}

bw.write(12);
bw.newLine();

for(int k = 0; k < 82; k++)
{
bw.write(k);
bw.newLine();
bw.write(k*5);
bw.newLine();

//do some additional code here

bw.write(2);
bw.newLine();
bw.write(k*4);
bw.newLine();
}

тогда заканчивай. Конечно, числа и так далее являются заполнителями, и на самом деле все, начиная от записи данных и заканчивая суммами циклов, являются переменными данными, которые я читаю из другого файла.

Как видите, я не могу использовать традиционную "цепочку методов", которая поставляется с JSR-353.

Что касается цепочки методов, взгляните на wiki http://en.wikipedia.org/wiki/Method_chaining. Примером связывания методов с использованием потокового API может быть такой, как показано в приведенном выше руководстве:

FileWriter writer = new FileWriter("c:\\example.txt");
JsonGenerator gen = Json.createGenerator(writer);

gen.writeStartObject()
   .write("firstName", "Duke")
   .write("lastName", "Java")
   .write("age", 18)
   .write("street/Address", "100 Internet Dr")
   .write("city", "JavaTown")
   .write("state", "JA")
   .write("postalCode", "12345")
   .writeStartArray("phoneNumbers")
      .writeStartObject()
         .write("type", "mobile")
         .write("number", "111-111-1111")
      .writeEnd()
      .writeStartObject()
         .write("type", "home")
         .write("number", "222-222-2222")
      .writeEnd()
   .writeEnd()
.writeEnd();
gen.close();

Я также посмотрел Учебное пособие по Oracle, которое немного смутило меня, когда я увидел "Генерирование / анализ", когда искал способ сохранить файлы.

https://docs.oracle.com/javaee/7/tutorial/doc/jsonp001.htm

19.1.3 Генерация и анализ данных JSON

Для генерации и анализа данных JSON существуют две модели программирования, которые аналогичны тем, которые используются для документов XML.

Модель потоковой передачи использует анализатор на основе событий, который читает данные JSON по одному элементу за раз. Парсер генерирует события и останавливается для обработки, когда объект или массив начинается или заканчивается, когда он находит ключ или когда он находит значение. Каждый элемент может быть обработан или отброшен кодом приложения, а затем анализатор переходит к следующему событию. Этот подход подходит для локальной обработки, при которой обработка элемента не требует информации от остальных данных. Потоковая модель генерирует вывод JSON для данного потока, вызывая функцию с одним элементом за раз.

Учебник упоминает об этом, но это сбивало с толку именно то, что это значит, особенно я думал, что это для письма, а не для чтения. Когда в нем упоминалась последняя строка (жирным шрифтом), не имело особого смысла, почему он делал это по одному, и создавалось впечатление, что он имеет дело только с частью объекта, а не с целым, как упоминает Object API. иметь дело со всем деревом.

Поэтому вместо того, чтобы работать с Streaming API, я начал с Object API. Я попытался сохранить файл сначала в FileWriter, но ничего не будет сохранено. В конце концов я переключился на StringWriter и использовал это в своем проекте. Я решил вернуться к FileWriter после завершения моей структуры, и он каким-то образом сохранился в файле, но я понимаю, что часть моего кода была обрезана в конце. Я пытался создать крошечную структуру, и она ничего не печатала.

2 ответа

Решение

Теперь отвечу на мой вопрос.

Это была какая-то странная ошибка, которая позволила мне записать в файл, используя Object API, потому что, очевидно, Object API предназначен не для сохранения каких-либо данных, а просто для сохранения их в качестве Object. Целью Streaming API является сохранение или отправка в поток, но не сохранение вообще. Приятно и удобно иметь оба варианта на случай, если нам понадобится либо либо, либо.

После этой проблемы я решил вернуться к Streaming API, и он работает, поэтому я хотел поделиться своим ответом как для Streaming API, так и для Object API, так как оба имеют разные способы кодирования этого.

Потоковый API с использованием метода-цепочки

private static void buildJsonUsingStreamingApi() {

  //Create a StringWriter instance to buffer the JSON data.
  StringWriter writer = new StringWriter();

  //Create a JSON generator backed by the StringWriter instance created above.
  JsonGenerator generator = Json.createGenerator(writer);

  //Start building the JSON Data- Uses Method chaining technique.
  //The JSON data gets streamed in the buffer as and when the
  //different methods are invoked.
  generator.writeStartArray()
            .writeStartObject()//Indicates the start of an JSON object
              .write("parentid", 23424900)
              .write("name","Mexico City")
              .write("url", "http://where.yahooapis.com/v1/place/116545")
              .writeStartObject("placeType")//Creating a nested object i.e an JSON object withing another object
                .write("name","Town")
                .write("code", 7)
              .writeEnd()
              .write("woeid", 116545)
            .writeEnd()//Indicates the end of an JSON object
            .writeStartObject()
              .write("name","Jackson")
              .write("url", "http://where.yahooapis.com/v1/place/2428184")
              .writeStartObject("placeType")
                .write("name","Town")
                .write("code", 7)
              .writeEnd()
            .write("parentid", 23424977)
            .write("woeid", 2428184)
            .writeEnd()
          .writeEnd();//Indicates the end of the JSON array.
  //Writes the data in the buffer to the String buffer.
  generator.flush();

  //Prints the JSON data onto the console.
  System.out.println(writer.toString());
}

Выход:

[
 {
   "parentid": 23424900,
   "name": "Mexico City",
   "url": "http://where.yahooapis.com/v1/place/116545",
   "placeType": {
     "name": "Town",
     "code": 7
   },
   "woeid": 116545
 },
 {
   "name": "Jackson",
   "url": "http://where.yahooapis.com/v1/place/2428184",
   "placeType": {
     "name": "Town",
     "code": 7
   },
   "parentid": 23424977,
   "woeid": 2428184
 }
]

Теперь, как вы можете видеть прямой подход, но я не могу сделать это с моим приложением, поэтому я так и сделал.

Потоковый API без метода-цепочки

         FileWriter fw = new FileWriter("c:\\example.txt");

        JsonGenerator gen = Json.createGenerator(fw);
        JsonGenerator mainObj = gen.writeStartObject(); //create your start object from the generator

        mainObj.write("object1", 10); //write value:key pairs as needed
        mainObj.write("object2", 1);
        mainObj.write("object3", 11);
        mainObj.write("object4", 11);
        mainObj.write("object5", 12); 

        JsonGenerator loop1 = mainObj.writeStartArray("Loop1"); //When needing to create a new 
                                                               //Array create a new start array                                                                                         
       for(int i = 0; i < 2; i++)     //based on the parent Object/Array, in this case "mainObj."
          loop1.write(5);            //could method chain

        loop1.writeEnd(); //in this case I did not need to create a new  
                          //object for each as I have only one element.

        JsonGenerator loop2 = mainObj.writeStartArray("Loop2"); //same as above to create Array.
        JsonGenerator loopObj2;                                //create new object 


        for(int i = 0; i < 9; i++)
        {

           loopObj2 = loop2.writeStartObject();         //using method-chaining with inner object
                   .write("LoopItem1",10)               //creates an object each time from loop2.
                   .write("LoopItem2",12).writeEnd();   //note method-chaining doesn't have to be 
                                                        //used here
              /*loop2.writeStartObject()                //If we switched to using this code we 
                .write("LoopItem1",10)                  //would be stuck with method-chaining.    
               .write("LoopItem2",12).writeEnd();*/     //loopObj2 isn't needed technically.

        }
        loop2.writeEnd();

        JsonGenerator loop3 = mainObj.writeStartArray("Loop3"); //same as above
        JsonGenerator loopObj3; //same as above

         for(int i = 0; i < 3; i++)
        {
             loopObj3 = loop3.writeStartObject(); //create new object from loop3.
                                                 //note this is exactly the same as above, we 
                                                //just don't use method chaining here, even                 
                                               //though we could chain the first 3



            loopObj3.write("LoopItem1", 57);
            loopObj3.write("LoopItem2", 67);
            loopObj3.write("LoopItem3", 0);
            System.out.println("Breaking Method-Chain just to do it...");
            loopObj3.write("LoopItem4", 9);
            loopObj3.writeEnd();                
        }

        loop3.writeEnd();
        mainObj.writeEnd();
        gen.close();

Выход:

{  
   "object1":10,
   "object2":1,
   "object3":11,
   "object4":11,
   "object5":12,
   "Loop1":[  
      5,
      12,
      5,
      12
   ],
   "Loop2":[  
      {  
         "LoopItem1":10,
         "LoopItem2":12
      },
      {  
         "LoopItem1":10,
         "LoopItem2":12
      },
      {  
         "LoopItem1":10,
         "LoopItem2":12
      },
      {  
         "LoopItem1":10,
         "LoopItem2":12
      },
      {  
         "LoopItem1":10,
         "LoopItem2":12
      },
      {  
         "LoopItem1":10,
         "LoopItem2":12
      },
      {  
         "LoopItem1":10,
         "LoopItem2":12
      },
      {  
         "LoopItem1":10,
         "LoopItem2":12
      },
      {  
         "LoopItem1":10,
         "LoopItem2":12
      }
   ],
   "Loop3":[  
      {  
         "LoopItem1":57,
         "LoopItem2":67,
         "LoopItem3":0,
         "LoopItem4":9
      },
      {  
         "LoopItem1":57,
         "LoopItem2":67,
         "LoopItem3":0,
         "LoopItem4":9
      },
      {  
         "LoopItem1":57,
         "LoopItem2":67,
         "LoopItem3":0,
         "LoopItem4":9
      }
   ]
}

Я также хотел показать, как я могу выполнить цикл 3, используя как цепочку методов, так и вызов.

            loopObj3.write("LoopItem1", 57)
            .write("LoopItem2", 67)
            .write("LoopItem3", 0);

            System.out.println("Breaking Method-Chain just to do it...");

            loopObj3.write("LoopItem4", 9);
            loopObj3.writeEnd();  

Объектный API с методом-цепочкой

    private static void buildJsonUsingObjectModelApi() {
  System.out.println("Json Building using Object Model API");
  JsonArray jsonArray =
          //Create an Array Builder to build an JSON Array
          Json.createArrayBuilder()
            .add(Json.createObjectBuilder()//Create an Object builder to build JSON Object
              .add("parentid", 23424900)
              .add("name","Jackson")
              .add("url", "http://where.yahooapis.com/v1/place/2428184")
              .add("placeType", Json.createObjectBuilder()//Another nested JSON Object
                    .add("name", "Town")
                    .add("code",7)
                  )
              .add("woeid", 116545)
              .build()//The JSON Object completely constructed.
            )
            .add(Json.createObjectBuilder()//Another object builder to build JSON Object.
              .add("name","Mexico City")
              .add("url", "http://where.yahooapis.com/v1/place/116545")
              .add("placeType", Json.createObjectBuilder()
                    .add("name", "Town")
                    .add("code",7)
                  )
              .add("parentid", 23424977)
              .add("woeid", 2428184)
              .build()
             )
            .build();
  StringWriter writer = new StringWriter();

  //Extracting the JSON data from the JSON object tree into the string.
  Json.createWriter(writer).writeArray(jsonArray);

  System.out.println(writer.toString());

}

Выход:

    [
   {
      "parentid":23424900,
      "name":"Jackson",
      "url":"http://where.yahooapis.com/v1/place/2428184",
      "placeType":{
         "name":"Town",
         "code":7
      },
      "woeid":116545
   },
   {
      "name":"Mexico City",
      "url":"http://where.yahooapis.com/v1/place/116545",
      "placeType":{
         "name":"Town",
         "code":7
      },
      "parentid":23424977,
      "woeid":2428184
   }
]

API объекта без цепочки методов

            JsonObjectBuilder mainObj = Json.createObjectBuilder();

            mainObj.add("object1", 10);
            mainObj.add("object2", 1);
            mainObj.add("object3", 11);
            mainObj.add("object4", 11);
            mainObj.add("object5", 12); 

            JsonArrayBuilder loop1 = Json.createArrayBuilder();
            for(int i = 0; i < 2; i++)
                loop1.add(i);

            mainObj.add("Loop1", loop1);


            JsonArrayBuilder loop2 = Json.createArrayBuilder();
            for(int i = 0; i < 9; i++)
            {


                loop2.add(Json.createObjectBuilder()
                .add("LoopItem1",10)
                .add("LoopItem2",12));
            }
            mainObj.add("Loop2",loop2);




            JsonArrayBuilder loop3 = Json.createArrayBuilder();
            JsonObjectBuilder loop3Obj;
            for(int i = 0; i < 3; i++)
            {
                loop3Obj = Json.createObjectBuilder()
                .add("LoopItem1", 57)
                .add("LoopItem2", 67)
                .add("LoopItem3", 0);
                System.out.println("Breaking Method-Chain just to do it...");
                loop3Obj.add("LoopItem4", 9);


             loop3.add(loop3Obj);

            }

                mainObj.add("Loop3", loop3);

        JsonObject planObj = mainObj.build();
            StringWriter writer = new StringWriter();
            JsonWriter jwrite = Json.createWriter(writer);
            jwrite.write(planObj);
             System.out.println(planObj.toString());

Выход:

   {
   "object1":10,
   "object2":1,
   "object3":11,
   "object4":11,
   "object5":12,
   "Loop1":[
      0,
      1
   ],
   "Loop2":[
      {
         "LoopItem1":10,
         "LoopItem2":12
      },
      {
         "LoopItem1":10,
         "LoopItem2":12
      },
      {
         "LoopItem1":10,
         "LoopItem2":12
      },
      {
         "LoopItem1":10,
         "LoopItem2":12
      },
      {
         "LoopItem1":10,
         "LoopItem2":12
      },
      {
         "LoopItem1":10,
         "LoopItem2":12
      },
      {
         "LoopItem1":10,
         "LoopItem2":12
      },
      {
         "LoopItem1":10,
         "LoopItem2":12
      },
      {
         "LoopItem1":10,
         "LoopItem2":12
      }
   ],
   "Loop3":[
      {
         "LoopItem1":57,
         "LoopItem2":67,
         "LoopItem3":0,
         "LoopItem4":9
      },
      {
         "LoopItem1":57,
         "LoopItem2":67,
         "LoopItem3":0,
         "LoopItem4":9
      },
      {
         "LoopItem1":57,
         "LoopItem2":67,
         "LoopItem3":0,
         "LoopItem4":9
      }
   ]
}

Первые 3 цепочки, затем у меня есть мой блокировщик, который просто println, а затем я пишу другой элемент, а затем writeEnd() с отдельными вызовами методов.

Теперь некоторые из вас могут жаловаться "но вы используете цепочку методов в вашем единственном внутреннем объекте!!!" да, да, но, как я уже говорил, мне не нужно было, и я хотел объяснить, что я могу сделать это с этим или без него, и даже использовать оба вместе, чтобы показать гибкость.

Я надеюсь, что это поможет другим. Мне потребовалось несколько дней, чтобы изучить и понять API, поэтому я хотел поделиться своими выводами. Мне также потребовалось около 3-4 часов, чтобы написать это руководство, поэтому я надеюсь, что оно действительно пригодится, и людям оно понравится.

Спасибо всем:).

Говорят, ребята из Oracle, ссылка на учебник по JSR 353 была изменена. Ссылка сейчас:

http://docs.oracle.com/javaee/7/tutorial/jsonp.htm

(tutorial / jsonp.htm вместо tutorial /doc/jsonp.htm)

Ссылка "Документация" также была исправлена ​​здесь:

https://jsonp.java.net/

и может быть более надежной ссылкой, чтобы ссылаться вместо прямых ссылок на учебник.

ОП может захотеть редактировать с этим обновлением.

Другие вопросы по тегам