js用什么解析json数据最方便,java json对比
java基础教程栏目介绍Java JSON的解析器
如何解决写爬虫IP受阻的问题?立即使用。
推荐(免费):java基础教程
在当今的编程世界中,JSON已经成为从客户机向服务器传输信息的首选协议。毫不夸张地说,XML是被弄死在沙滩上的浪潮。
不幸的是,JDK没有JSON库,所以我不知道为什么没有。在Log4j,为了竞争,引入了java.util.logging,虽然最后用的人不多。
Java之所以牛逼,是因为它的生态非常完整。JDK没有JSON库,但是第三方类库有,这很好。比如猪脚——Jackson,GitHub superscript 6.1k,以及本文中Spring Boot默认的JSON解析器。
这怎么证明?
当我们通过starter创建一个新的Spring Boot Web项目时,我们可以在Maven的dependencies中看到Jackson。
杰克逊有许多优点:
解析大文件的速度更快;运行库占用的内存更少,性能更好;API灵活,易于扩展和定制。杰克逊的核心模块由三部分组成:
核心包Jackson-core提供了基于“流模式”解析的相关API,包括JsonPaser和JsonGenerator。Jackson-annotations,注释包,提供标准的注释功能;数据绑定包Jackson-databind提供了基于“对象绑定”分析的相关API (ObjectMapper)和基于“树模型”分析的相关API (JsonNode)。
01、引入 Jackson 依赖
要使用Jackson,您需要在pom.xml文件中添加Jackson的依赖项。
属国
groupId com . faster XML . Jackson . core/groupId
artifactId Jackson-databind/artifactId
版本2 . 10 . 1/版本
/dependencyjackson-databind依赖于jackson-core和jackson-annotations,所以在添加jackson-databind后,Maven会自动将jackson-core和jackson-annotations引入到项目中。
这就是Maven吸引人的地方。它可以暗中帮助我们做我们必须做的事情。
02、使用 ObjectMapper
Jackson最常用的API是基于“对象绑定”的ObjectMapper,它通过writeValue的一系列方法将Java对象序列化为JSON,并可以不同格式存储。
将对象存储为字符串的WriteValueAsString(对象值)方法,将对象存储为字节数组的writeValueAsBytes(对象值)方法,将对象存储为文件的WriteValue(文件结果文件,对象值)方法。让我们来看看存储为字符串的代码示例:
import com . faster XML . Jackson . core . jsonprocessingexception;
导入com . faster XML . Jackson . databind . object mapper;
/**
*微信搜索“寂静王二”,回复Java
*
* @作者沉默王二
* @日期2020年11月26日
*/
公开课演示{
公共静态void main(String[] args)引发JsonProcessingException {
作家wanger=新作家(沉默的国王二,18);
object mapper mapper=new object mapper();
string JSON string=mapper . writerwithdefaultprettyprinter()。writeValueAsString(wanger);
system . out . println(JSON string);
}
}
类编写器{
私有字符串名称;
私人年龄;
公共编写器(字符串名称,整数){
this.name=name
this.age=年龄;
}
公共字符串getName() {
返回名称;
}
public void setName(字符串名){
this.name=name
}
public int getAge() {
回归年龄;
}
公共无效存储(整数){
this.age=年龄;
}
}程序输出结果如下:
{
姓名:沉默王二,
“年龄”:18岁
}并非所有字段都支持序列化和反序列化,以下规则是必需的:
如果字段的修饰符是公共的,则该字段可序列化和反序列化(不是标准写法)。如果字段的修饰符不是公共的,但是它的吸气剂方法和作曲者方法是公共的,则该字段可序列化和反序列化吸气剂。方法用于序列化,setter方法用于反序列化。如果字段只有公众的的作曲者方法,而无公众的的吸气剂方法,则该字段只能用于反序列化。如果想更改默认的序列化和反序列化规则,需要调用对象映射器的setVisibility()方法。否则将会抛出InvalidDefinitionException异常。
对象映射器通过读取值的系列方法从不同的数据源将数据反序列化为爪哇对象。
读取值(字符串内容,ClassT值类型)方法,将字符串反序列化为爪哇对象readValue(byte[] src,ClassT valueType)方法,将字节数组反序列化为爪哇对象读取值(文件src,ClassT值类型)方法,将文件反序列化为爪哇对象来看一下将字符串反序列化为爪哇对象的代码示例:
导入com。更快的XML。杰克逊。核心。jsonprocessingexception
导入com。更快的XML。杰克逊。数据绑定。对象映射器;
/**
* 微信搜索「沉默王二」,回复爪哇
*
* @作者沉默王二
* @日期2020年11月26日
*/
公开课演示{
公共静态void main(String[] args)引发JsonProcessingException {
对象映射器mapper=新对象映射器();
String jsonString={\n
\ 名称\ : \ 沉默王二\ ,\n
\ 年龄\ : 18\n
};
编写器反序列化编写器=映射器。读取值(JSON字符串,编写器。类);
系统。出去。println(反序列化编写器);
}
}
类编写器{
私有字符串名称;
私人年龄;
//getter/setter
@覆盖
公共字符串toString() {
返回"作家{ "
name= name \
,年龄=年龄
};
}
}程序输出结果如下所示:
编写器{name=沉默王二,年龄=18}PS:如果反序列化的对象有带参的构造方法,它必须有一个空的默认构造方法,否则将会抛出InvalidDefinitionException一行。
线程“主”通讯器。更快的XML。杰克逊。数据绑定。exc。invaliddefinitionexception中出现异常:无法构造" com.itwanger.jackson.Writer "的实例(不存在创建者,如默认构造):无法从对象值反序列化(没有基于委托或基于属性的创建者)
在[Source: (String){
姓名 : 沉默王二,
"年龄":18岁
};第2行,第3列]
在com。更快的XML。杰克逊。数据绑定。exc。invaliddefinitionexception。from(invaliddefinitionexception。Java:67)
在com。更快的XML。杰克逊。数据绑定。沙漠化语境。reportbaddefinition(去化上下文。Java:1589)
在com。更快的XML。杰克逊。数据绑定。反序列化上下文。handlemissinginstantiator(反序列化上下文。Java:1055)
在com。更快的XML。杰克逊。数据绑定。活该。豆子沙漠基地。deserialfromobjectusingnondefault(bean deserialierbase。Java:1297)
在com。更快的XML。杰克逊。数据绑定。活该。bean反序列化程序。deserialfromobject(bean反序列化程序。Java:326)
位于com。更快的XML。杰克逊。数据绑定。活该。bean反序列化程序。反序列化(bean反序列化器。Java:159)
位于com。更快的XML。杰克逊。数据绑定。对象映射器。_ readMapAndClose(对象映射器。Java:4202)
位于com。更快的XML。杰克逊。数据绑定。对象映射器。读取值(对象映射器。Java:3205)
位于com。更快的XML。杰克逊。数据绑定。对象映射器。读取值(对象映射器。Java:3173)
在com。它旺格。杰克逊。演示。主(演示。爪哇:19)杰克逊最常用的应用程序接口就是基于"对象绑定"的对象映射器,
对象映射器也可以将数据解析为基于"树模型"的JsonNode对象,来看下面的示例。
导入com。更快的XML。杰克逊。核心。jsonprocessingexception
导入com。更快的XML。杰克逊。数据绑定。JSON节点;
导入com。更快的XML。杰克逊。数据绑定。对象映射器;
/**
* 微信搜索「沉默王二」,回复爪哇
*
* @作者沉默王二
* @日期2020年11月26日
*/
公共类JsonNodeDemo {
公共静态void main(String[] args)引发JsonProcessingException {
对象映射器mapper=新对象映射器();
字符串json={ \name\ : \ 沉默王二\ ,\ 年龄\ :18 } ;
JSON节点JSON节点=映射器。读树(JSON);
String name=jsonNode.get(name ).as text();
System.out.println(名称);//沉默王二
}
}借助类型引用可以将数据字符串数组转成泛型列表,来看下面的示例:
导入com。更快的XML。杰克逊。核心。jsonprocessingexception
导入com。更快的XML。杰克逊。核心。类型。类型引用;
导入com。更快的XML。杰克逊。数据绑定。对象映射器;
导入Java。util。列表;
/**
* 微信搜索「沉默王二」,回复爪哇
*
* @作者沉默王二
* @日期2020年11月26日
*/
公共类TypeReferenceDemo {
公共静态void main(String[] args)引发JsonProcessingException {
对象映射器mapper=新对象映射器();
String json=[{ \name\ : \ 沉默王三\ ,\ 年龄\ : 18 },{ \ 姓名\ : \ 沉默王二\ ,\ age \ :19 }];
列表作者列表作者=映射器。read value(JSON,new typereferencelistathor(){ });
系统。出去。println(列表作者);
}
}
类别作者{
私有字符串名称;
私人年龄;
//getter/setter
//toString
}
03、更高级的配置
杰克逊之所以牛掰的一个很重要的因素是可以实现高度灵活的自定义配置。
在实际的应用场景中,JSON中常常会有一些爪哇对象中没有的字段,这时候,如果直接解析的话,会抛出无法识别的属性异常异常。
下面是一串数据字符串:
String jsonString={\n
\ 名称\ : \ 沉默王二\ ,\n
\ 年龄\ : 18\n
\ 性\ : \ 男\ ,\n
};但爪哇对象作者中没有定义性字段:
类编写器{
私有字符串名称;
私人年龄;
//getter/setter
}我们来尝试解析一下:
对象映射器mapper=新对象映射器();
编写器反序列化编写器=映射器。读取值(JSON字符串,编写器。类);不出意外,抛出异常了,性无法识别。
线程“主”通讯器。更快的XML。杰克逊。数据绑定。exc。无法识别的属性异常中的异常:无法识别的字段《性》(class com。它旺格。杰克逊。作家),未标记为可忽略(2个已知属性:"姓名"、"年龄"])
在[Source: (String){
姓名 : 沉默王二,
年龄:18岁,
性 : 男
};第四行,第12列](通过引用链:com。它旺格。杰克逊。作家[性])怎么办呢?可以通过配置()方法忽略掉这些"无法识别"的字段。
mapper.configure(反序列化功能FAIL_ON_UNKNOWN_PROPERTIES,false);除此之外,还有其他一些有用的配置信息,来了解一下:
//在序列化时忽略值为空的属性
制图师。setserializationinclude(JSON include .包括。NON _ NULL);
//忽略值为默认值的属性
制图师。setdefaultpropertypinclusion(JSON include .包括。非_默认);
04、处理日期格式
对于日期类型的字段,比如说java.util.Date,如果不指定格式,序列化后将显示为长的类型的数据,这种默认格式的可读性很差。
{
年龄:18岁,
"生日":1606358621209
}怎么办呢?
第一种方案,在吸气剂上使用@JsonFormat注解。
私人约会生日;
//GMT 8是指格林尼治的标准时间,在加上八个小时表示你现在所在时区的时间
@JsonFormat(timezone=GMT 8 ,pattern=yyyy-MM-dd HH:mm:ss )
公共日期getBirthday() {
回生日;
}
public void setBirthday(日期生日){
this.birthday=生日;
}再来看一下结果:
{
年龄:18岁,
生日: 2020-11-26 03:02:30
}具体代码如下所示:
对象映射器mapper=新对象映射器();
作家王二=新作家(沉默王二, 18);
王二。设置生日(新日期());
字符串JSON字符串=映射器。writerwithdefaultprettyprinter()。writeValueAsString(wanger);
系统。出去。println(JSON字符串);第二种方案,调用对象映射器的setDateFormat()方法。
对象映射器mapper=新对象映射器();
制图师。设置日期格式(stddate格式。getdatetimeinstance());
作家王二=新作家(沉默王二, 18);
王二。设置生日(新日期());
字符串JSON字符串=映射器。writerwithdefaultprettyprinter()。writeValueAsString(wanger);
系统。出去。println(JSON字符串);输出结果如下所示:
{
姓名 : 沉默王二,
年龄:18岁,
生日:2020年年11月26日上午11:09:51
}
05、字段过滤
在将爪哇对象序列化为数据时,可能有些字段需要过滤,不显示在数据中,杰克逊有一种比较简单的实现方式。
@JsonIgnore用于过滤单个字段。
@JsonIgnore
公共字符串getName() {
返回名称;
}@JsonIgnoreProperties用于过滤多个字段。
@ JsonIgnoreProperties(value={ age , birthday })
类编写器{
私有字符串名称;
私人年龄;
私人约会生日;
}
06、自定义序列化和反序列化
当杰克逊默认序列化和反序列化不能满足实际的开发需要时,可以自定义新的序列化和反序列化类。
自定义的序列化类需要继承StdSerializer,同时重写序列化()方法,利用写生成JSON,示例如下:
/**
* 微信搜索「沉默王二」,回复爪哇
*
* @作者沉默王二
* @日期2020年11月26日
*/
公共类自定义序列化程序扩展StdSerializerMan {
受保护的CustomSerializer(ClassMan t) {
超(t);
}
public CustomSerializer() {
这个(空);
}
@覆盖
公共无效序列化(人工值、JsonGenerator gen、SerializerProvider提供程序)引发IOException {
gen . writestartobject();
gen.writeStringField(name ,value。getname());
gen . writeendobject();
}
}
阶级男人{
私人年龄;
私有字符串名称;
public Man(int age,String name) {
this.age=年龄;
this.name=name
}
public int getAge() {
回归年龄;
}
公共无效存储(整数){
this.age=年龄;
}
公共字符串getName() {
返回名称;
}
公共void集合名称(字符串名){
this.name=name
}
}定义好自定义序列化类后,要想在程序中调用它们,需要将其注册到对象映射器的组件中,示例如下所示:
对象映射器mapper=新对象映射器();
简单模块模块=
新的简单模块(“自定义序列化程序”,新版本(1,0,0,null,null));
module.addSerializer(Man.class,new custom serializer());
mapper.registerModule(模块);
曼曼=新人类(18,沉默王二);
字符串JSON=mapper。writevalueasstring(man);
系统。出去。println(JSON);程序输出结果如下所示:
{ 姓名:沉默王二}自定义序列化类自定义序列化程序中没有添加年龄字段,所以只输出了名字字段。
再来看一下自定义的反序列化类,继承StdDeserializer,同时重写反序列化()方法,利用写读取JSON,示例如下:
公共类自定义反序列化程序扩展了StdDeserializerWoman {
受保护的自定义反序列化程序(类vc) {
超级(VC);
}
公共CustomDeserializer() {
这个(空);
}
@覆盖
公共妇女反序列化(JsonParser p,反序列化上下文ctxt)引发IOException,JsonProcessingException {
JsonNode node=p.getCodec().读树(p);
女人女人=新女人();
int age=(Integer)((int node)节点。get( age ).数值();
String name=node.get(name ).as text();
女人. setAge(年龄);
woman.setName(名称);
回归女人;
}
}
班级妇女{
私人年龄;
私有字符串名称;
公共女性(){
}
//getter/setter
@覆盖
公共字符串toString() {
返回"女人"
年龄=年龄
,name= name \
};
}
}通过JsonNode把数据读取到一个树形结构中,然后通过JsonNode的得到方法将对应字段读取出来,然后生成新的爪哇对象,并返回。
定义自定义反序列化类后,如果要在程序中调用,还需要在ObjectMapper的模块中注册。示例如下:
object mapper mapper=new object mapper();
简单模块模块=
new simple module( custom deserializer ,新版本(1,0,0,null,null,null));
module . add deserializer(woman . class,new custom deserializer());
mapper.registerModule(模块);
JSON= {\ name \: \ 三姐\ ,\ age \ :18 } ;
woman woman=mapper . read value(JSON,woman . class);
System.out.println(女子);程序输出结果如下:
女人{age=18,name=三姐 }
07、结语
哦,好像不错。杰克逊绝对配得上“最牛逼”这四个字,虽然有点虚。如果只想进行简单的序列化和反序列化,可以使用ObjectMapper的write和read方法。
如果想更进一步,需要自定义ObjectMapper,或者添加一些注释,直接自定义序列化和反序列化类,更接近一些Java对象。
应该注意的是,您应该对日期格式的字段更加小心,尽量不要使用默认配置,因为默认配置可读性很差。
好了,通过本文的系统介绍,相信你已经对杰克逊有了充分的了解。下一篇文章再见。
PS:如果你正好需要一本Java递进路线,我这里有一本。我花了差不多3天才整理出来,还挺受欢迎的。已经2000多赞了,每个阶段都很细致。
以上是Java JSON解析器的细节:Jackson,我认为是最好的。请多关注我们的其他相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。