6

我想通过使用新的 JSR-353 来分享我的问题/答案,它是用于 JSON 处理的 Java API。具体来说,您可以在 2 个不同的“API”流和对象 API 中操作 JSON 数据。

如果你在谷歌中输入“jsr-353 教程”,你会得到很多结果。

https://jcp.org/en/jsr/detail?id=353 ~ 具体请求的详细信息。

https://jsonp.java.net/ ~ API 的主站点,还将您链接到位于https://docs.oracle.com/javaee/7/tutorial/doc/jsonp 的“文档”下的 Oracle 教程。 htm 我稍后会详细讨论本教程。

最后是这个

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

我想先谈谈最后一个链接,因为它为我提供了很多很好的细节,也是目前仅有的真正教程之一(还有其他的,但它们基本相同)。

我真正尝试了解的 API 从新到不仅是这个 API,而且是一般的 JSON。

何时使用 Streaming API 和 Object Model API?

如果您希望将 JSON 数据写入像文件这样的字符流或字节流,那么 Streaming API 将是最佳选择,因为它直接执行写入缓冲区的操作,而无需在内存中构造对象树,即那里不是在创建最终 JSON 数据之前生成的中间形式。

如果您想将 JSON 数据作为对象树保存在内存中,即不写入任何流,而是将树存储在内存中,以便可以重用 JSON 数据而无需重新解析它,或者也可以将对象树序列化为持久化/保存 JSON 数据。这里 JSON 数据将以对象树的形式表示。

现在,Streaming API 描述对我来说很有意义,我需要保存一个文件,所以这对我来说很有意义。

至于对象 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。使用 Streaming 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 并以某种方式保存到文件中,但我意识到我的部分代码在最后被切断了。我试着做一个很小的结构,它什么也不会打印。

4

2 回答 2

8

现在回答我的问题。

这是一个奇怪的错误,允许我使用 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 个小时来写这个教程,所以我希望它确实有用,人们喜欢它。

谢谢大家:)。

于 2014-11-09T21:18:57.257 回答
-2

与 Oracle 人员交谈,JSR 353 教程链接已更改。现在的链接是:

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

(tutorial/jsonp.htm 而不是 tutorial/ doc / jsonp.htm)

“文档”链接也已在此处修复:

https://jsonp.java.net/

并且可能是一个更可靠的链接来参考而不是直接链接到教程。

OP 可能希望使用此更新进行编辑。

于 2015-07-22T00:38:56.063 回答