我想使用新的JSR-353(用于JSON处理的JavaAPI)与大家分享我的问题/答案。具体地说,您可以在两种不同的“API”中操作JSON数据:流和对象API。
如果你在谷歌上输入“jsr-353教程”,你会得到很多结果。
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,而且是JSON的新成员。
如果您希望将JSON数据写入字符流(如文件或字节流),那么Streaming API将是最佳选择,因为它直接执行写入缓冲区的操作,而无需在内存中构建对象树不是在创建最终JSON数据之前生成的中间表单。
如果您希望将JSON数据作为对象树保存在内存中,即不写入任何流,而是将树存储在内存中,这样就可以重用JSON数据,而无需重新分析它,或者还可以序列化对象树以持久化/保存JSON数据。这里,JSON数据将以对象树的形式表示。
现在,流式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();
}
然后结束。这些数字都是占位符,实际上,从写入数据到循环量的所有内容都是我从另一个文件读取的变量数据。
如您所见,我不能使用JSR-353附带的传统“方法链接”。
至于什么是方法链接,看看wikihttp://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
为了生成和解析JSON数据,有两种编程模型,它们类似于用于XML文档的模型。
流模型使用基于事件的解析器,每次读取一个元素的JSON数据。当对象或数组开始或结束、找到键或找到值时,解析器生成事件并停止处理。应用程序代码可以处理或丢弃每个元素,然后解析器继续处理下一个事件。这种方法适用于本地处理,在本地处理中,元素的处理不需要来自其余数据的信息。流模型通过每次调用一个元素来生成给定流的JSON输出。
教程中提到了这一点,但它确实混淆了这意味着什么,尤其是我认为这是为了写作而不是阅读。当它提到最后一行(粗体)时,它没有太多的意义,为什么它一次只做一行,并且似乎它只处理对象的一部分,而不是整个,正如对象API提到的处理整个树。
因此,我没有处理流式API,而是从对象API开始。起初我尝试将文件保存到FileWriter,但什么也不会保存。最后我换了一个StringWriter,并在我的项目中使用它。在完成我的结构后,我决定切换回FileWriter,它以某种方式保存到文件中,但我意识到我的部分代码在最后被切断了。我试着做一个很小的结构,但它什么也印不出来。
与Oracle的人交谈,JSR 353教程链接已经更改。链接现在是:
http://docs.oracle.com/javaee/7/tutorial/jsonp.htm
(教程/jsonp.htm而不是教程/文档/jsonp.htm)
此处还修复了“文档”链接:
https://jsonp.java.net/
这可能是一个更可靠的参考链接,而不是教程的直接链接。
OP可能希望使用此更新进行编辑。
这是一个奇怪的错误,允许我使用对象API写入文件,因为显然对象API不是用来保存任何数据的,只是将其作为一个对象保存。流式API的目的是保存或发送到流,但根本不保存。这是很好的和方便的两种选择,以防我们需要做或。
在出现这个问题后,我决定切换回流式API,它可以工作,所以我想分享我对流式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
}
]
现在你可以看到直截了当的方法,但我不能用我的应用程序做到这一点,所以这就是我如何做到这一点。
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();
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
}
]
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()和单独的方法调用。
现在你们中的一些人可能会抱怨“但你们确实在一个内部对象中使用了方法链接!!!”是的,是的,我知道,但正如我所提到的,我不必这样做,我想解释一下,我可以用它来做这件事,也可以不用它,甚至可以将两者结合使用来显示灵活性。
我希望这能帮助其他人。这花了我几天时间来学习和理解应用编程接口,所以我想分享我的发现。我也花了大约3-4个小时来写这个教程,所以我希望它确实得到一些使用,人们喜欢它。
谢谢大家:)。
我有一个问题要解决,我应该在哪里从使用Java8 streams的员工列表中找到性别为男性的第n个员工,如果没有找到,则返回可选的空。 下面是接受Employee对象列表和整数n的方法,其中n表示必须返回的第n个男性雇员(如果存在的话)。
问题内容: 这是使用awt包的Java图形的初学者问题。我在网上找到了这段代码来绘制一些简单的图形。 在main方法中,在画布上没有调用paint()。但是我运行了该程序并且它可以工作,那么paint()方法如何运行? 问题答案: 该方法由事件调度线程(EDT)调用,并且基本上不受您的控制。 它的工作方式如下:当 实现 用户界面(以您的情况为例)时,Swing将启动EDT。然后,此EDT线程在后台
我有一个带有私有方法的类,该方法调用一些外部类并执行它,如果不使用powermock,我如何防止这种情况发生?(该项目使用Junit5,目前还不支持powermock)。 我考虑过将这些函数移到外面,但我觉得有时方法确实属于特定的类,因为它们是它的一部分,将它们移出对我来说没有意义,下面只是一个例子来说明。 我已经知道大多数人会说不要测试私有方法,但a.我不完全同意,b.我不想在这里测试这个方法,
问题内容: 有人建议可以怎一个JAVA程序运行不写一个主要方法.. 例如: 不使用类中的公共静态void main(String arg []),如何在控制台上打印以上行。 问题答案: 直到JDK6,您都可以使用静态初始化程序块来打印消息。这样,一旦您的班级被加载,消息就会被打印出来。然后,技巧就变成了使用另一个程序来加载您的类。 当然,您可以按如下方式运行程序,您将看到消息;但是,该命令也会失败
问题内容: 我想知道像Karel这样的程序可以运行机器人,因为它没有使用main()方法。相反,它使用run()方法: 它是如何工作的? 问题答案: 实际的主要方法在其他地方。例如,在KarelRunner类中。当Java执行程序时,它实际上是在运行程序类中执行main方法。从该运行程序代码中调用您自己的run方法。
我正在玩grpc 有人成功使用进行生产吗?我们需要包括特使在内的所有依赖项吗?