如何在没有方法链的情况下使用"JSR-353:用于JSON处理的Java API"

Xao*_*Bao 6 java json fluent-interface alternate jsr-353

我想与使用新的JSR-353(JSON Processing的Java API)分享我的问题/答案.具体来说,您可以在两个不同的"API"Streaming和Object 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 Tutorial . 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描述对我来说很有意义,我需要保存一个文件,这对我来说很有意义.

对于Object API,它也是有意义的,保存对象,以便我可以在以后的代码中重用它,真棒.

问题是我没有得到我的问题的答案,我将解释我现在正在寻找什么.

我的问题是:

我基本上有一个包含其他对象/数组的对象.

最初我使用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();
}
Run Code Online (Sandbox Code Playgroud)

然后完成.确定数字,这些是占位符,实际上从写入数据到循环量的所有内容都是我从另一个文件中读取的可变数据.

正如您所看到的,我无法使用JSR-353附带的传统"方法链".

至于链接的方法,请查看维基http://en.wikipedia.org/wiki/Method_chaining.使用Streaming API的Method Chaining的一个例子就是这个,如上面的教程所示:

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();
Run Code Online (Sandbox Code Playgroud)

我还看了一下Oracle Tutorial,当我在寻找一种保存文件的方法时,我看到了"Generating/Parsing".

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

19.1.3生成和解析JSON数据

为了生成和解析JSON数据,有两种编程模型,类似于用于XML文档的编程模型.

流模型使用基于事件的解析器,一次读取一个元素的JSON数据.当对象或数组开始或结束,找到键或找到值时,解析器生成事件并停止处理.应用程序代码可以处理或丢弃每个元素,然后解析器继续执行下一个事件.这种方法适用于本地处理,其中元素的处理不需要来自其余数据的信息.流模型通过一次使用一个元素进行函数调用来生成给定流的JSON输出.

该教程提到了这一点,但令人困惑的是这意味着什么,特别是我认为这是写作而不是阅读.当它提到最后一行(以粗体显示)时,为什么它会一次只执行一次并没有多大意义,并且使它看起来只处理对象的一部分而不是整体,如Object API所提到的那样处理整棵树.

因此,我开始使用Object API,而不是处理Streaming API.我尝试首先将文件保存到FileWriter,但不会保存任何内容.最后我切换到StringWriter并在我的项目中使用它.我决定在完成我的结构之后切换回FileWriter并以某种方式保存到文件中,但我意识到我的部分代码在最后被切断了.我试图做一个小结构,它什么都不打印.

Xao*_*Bao 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());
}
Run Code Online (Sandbox Code Playgroud)

输出:

[
 {
   "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
 }
]
Run Code Online (Sandbox Code Playgroud)

现在你可以看到直接的方法,但我不能用我的应用程序做到这一点,所以这就是我完成它的方法.

没有方法链接的流式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();
Run Code Online (Sandbox Code Playgroud)

输出:

{  
   "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
      }
   ]
}
Run Code Online (Sandbox Code Playgroud)

我还想展示如何使用方法链接和调用来完成循环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();  
Run Code Online (Sandbox Code Playgroud)

具有方法链接的对象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());

}
Run Code Online (Sandbox Code Playgroud)

输出:

    [
   {
      "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
   }
]
Run Code Online (Sandbox Code Playgroud)

没有方法链接的对象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());
Run Code Online (Sandbox Code Playgroud)

输出:

   {
   "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
      }
   ]
}
Run Code Online (Sandbox Code Playgroud)

前3个被链接,然后我有我的阻止器,它只是println,然后我写了另一个项目,然后writeEnd()与单独的方法调用.

现在有些人可能会抱怨"但你确实在你的一个内部对象中使用方法链接!!!" 是的,我是的,但正如我所提到的,我没有必要,而且我想解释一下,无论有没有这样做,我都可以用它们来表示灵活性.

我希望这有助于其他人.这花了我几天时间来学习和理解API,所以我想分享我的发现.我也花了大约3-4个小时来编写本教程,所以我希望它能得到一些用处,人们会喜欢它.

谢谢所有:).