高端网站建设哪些好做,wordpress 常用插件,网站建设 资讯动态,江苏省交通工程建设局网站前些天发现了一个巨牛的人工智能学习网站#xff0c;通俗易懂#xff0c;风趣幽默#xff0c;忍不住分享一下给大家。点击跳转到教程。
官方WIKI#xff1a;https://github.com/FasterXML/jackson-databind/wiki
jackson 1.x和2.x版本的注解是放置在不同的包下的
1.x是在…前些天发现了一个巨牛的人工智能学习网站通俗易懂风趣幽默忍不住分享一下给大家。点击跳转到教程。
官方WIKIhttps://github.com/FasterXML/jackson-databind/wiki
jackson 1.x和2.x版本的注解是放置在不同的包下的
1.x是在jackson core jar包org.codehaus.jackson.annotate下
2.x是在jackson-databind包com.fasterxml.jackson.annotation下 jackson的自动检测机制
jackson允许使用任意的构造方法或工厂方法来构造实例
使用JsonAutoDetect作用在类上来开启/禁止自动检测
fieldVisibility:字段的可见级别
ANY:任何级别的字段都可以自动识别
NONE:所有字段都不可以自动识别
NON_PRIVATE:非private修饰的字段可以自动识别
PROTECTED_AND_PUBLIC:被protected和public修饰的字段可以被自动识别
PUBLIC_ONLY:只有被public修饰的字段才可以被自动识别
DEFAULT:同PUBLIC_ONLY
jackson默认的字段属性发现规则如下
所有被public修饰的字段-所有被public修饰的getter-所有被public修饰的setter
举例 [java] view plain copy public static class TestPOJO{ TestPOJO(){} TestPOJO(String name){ this.name name; } private String name; Override public String toString() { return TestPOJO{ name name \ }; } } 这个类我们只有一个private的name属性并且没有提供对应的get,set方法如果按照默认的属性发现规则我们将无法序列化和反序列化name字段(如果没有get,set方法只有被public修饰的属性才会被发现)你可以通过修改JsonAutoDetect的fieldVisibility来调整自动发现级别为了使name被自动发现我们需要将级别调整为ANY [java] view plain copy JsonAutoDetect(fieldVisibility JsonAutoDetect.Visibility.ANY) 同理除了fieldVisibility可以设置外还可以设置getterVisibility、setterVisibility、isGetterVisibility、creatorVisibility级别不再多讲 除了上面的方式你还可以有一些其他方式可以配置methods,fields和creators(构造器和静态方法)的自动检测例如
你可以配置MapperFeature来启动/禁止一些特别类型(getters,setters,fields,creators)的自动检测
比如下面的MapperFeature配置
SORT_PROPERTIES_ALPHABETICALLY按字母顺序排序属性 [java] view plain copy ObjectMapper objectMapper new ObjectMapper(); objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY,true); 配置SerializationFeature 一些我们比较常用的SerializationFeature配置
SerializationFeature.WRAP_ROOT_VALUE是否环绕根元素默认false如果为true则默认以类名作为根元素你也可以通过JsonRootName来自定义根元素名称 [java] view plain copy objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE,true); 举例 [java] view plain copy JsonRootName(myPojo) public static class TestPOJO{ private String name; public String getName() { return name; } public void setName(String name) { this.name name; } } 该类在序列化成json后类似如下:{myPojo:{name:aaaa}} SerializationFeature.INDENT_OUTPUT是否缩放排列输出默认false有些场合为了便于排版阅读则需要对输出做缩放排列 [java] view plain copy objectMapper.configure(SerializationFeature.INDENT_OUTPUT,true); 举例
如果一个类中有a、b、c、d四个可检测到的属性那么序列化后的json输出类似下面
{ a : aaa, b : bbb, c : ccc, d : ddd }
SerializationFeature.WRITE_DATES_AS_TIMESTAMPS序列化日期时以timestamps输出默认true [java] view plain copy objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,true); 比如如果一个类中有private Date date;这种日期属性序列化后为{date : 1413800730456}若不为true则为{date : 2014-10-20T10:26:06.6040000} SerializationFeature.WRITE_ENUMS_USING_TO_STRING序列化枚举是以toString()来输出默认false即默认以name()来输出 [java] view plain copy objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING,true); SerializationFeature.WRITE_ENUMS_USING_INDEX序列化枚举是以ordinal()来输出默认false [java] view plain copy objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_INDEX,true); 举例 [java] view plain copy Test public void enumTest() throws Exception { TestPOJO testPOJO new TestPOJO(); testPOJO.setName(myName); testPOJO.setMyEnum(TestEnum.ENUM01); ObjectMapper objectMapper new ObjectMapper(); objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING,false); objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_INDEX,false); String jsonStr1 objectMapper.writeValueAsString(testPOJO); Assert.assertEquals({\myEnum\:\ENUM01\,\name\:\myName\},jsonStr1); ObjectMapper objectMapper2 new ObjectMapper(); objectMapper2.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING,true); String jsonStr2 objectMapper2.writeValueAsString(testPOJO); Assert.assertEquals({\myEnum\:\enum_01\,\name\:\myName\},jsonStr2); ObjectMapper objectMapper3 new ObjectMapper(); objectMapper3.configure(SerializationFeature.WRITE_ENUMS_USING_INDEX,true); String jsonStr3 objectMapper3.writeValueAsString(testPOJO); Assert.assertEquals({\myEnum\:0,\name\:\myName\},jsonStr3); } public static class TestPOJO{ TestPOJO(){} private TestEnum myEnum; private String name; //getters、setters省略 } public static enum TestEnum{ ENUM01(enum_01),ENUM02(enum_01),ENUM03(enum_01); private String title; TestEnum(String title) { this.title title; } Override public String toString() { return title; } } SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED序列化单元素数组时不以数组来输出默认false [java] view plain copy objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING,true); 举例 [java] view plain copy Test public void singleElemArraysUnwrap() throws Exception { TestPOJO testPOJO new TestPOJO(); testPOJO.setName(myName); ListInteger counts new ArrayList(); counts.add(1); testPOJO.setCounts(counts); ObjectMapper objectMapper new ObjectMapper(); objectMapper.configure(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED,false); String jsonStr1 objectMapper.writeValueAsString(testPOJO); Assert.assertEquals({\name\:\myName\,\counts\:[1]},jsonStr1); ObjectMapper objectMapper2 new ObjectMapper(); objectMapper2.configure(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED,true); String jsonStr2 objectMapper2.writeValueAsString(testPOJO); Assert.assertEquals({\name\:\myName\,\counts\:1},jsonStr2); } public static class TestPOJO{ private String name; private ListInteger counts; //getters、setters省略 } SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS序列化Map时对key进行排序操作默认false [java] view plain copy objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS,true); 举例 [java] view plain copy Test public void orderMapBykey() throws Exception { TestPOJO testPOJO new TestPOJO(); testPOJO.setName(myName); MapString,Integer counts new HashMap(); counts.put(a,1); counts.put(d,4); counts.put(c,3); counts.put(b,2); counts.put(e,5); testPOJO.setCounts(counts); ObjectMapper objectMapper new ObjectMapper(); objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS,false); String jsonStr1 objectMapper.writeValueAsString(testPOJO); Assert.assertEquals({\name\:\myName\,\counts\:{\d\:4,\e\:5,\b\:2,\c\:3,\a\:1}},jsonStr1); ObjectMapper objectMapper2 new ObjectMapper(); objectMapper2.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS,true); String jsonStr2 objectMapper2.writeValueAsString(testPOJO); Assert.assertEquals({\name\:\myName\,\counts\:{\a\:1,\b\:2,\c\:3,\d\:4,\e\:5}},jsonStr2); } public static class TestPOJO{ private String name; private MapString,Integer counts; //getters、setters省略 } SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS序列化char[]时以json数组输出默认false [java] view plain copy objectMapper.configure(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS,true); 举例 [java] view plain copy Test public void charArraysAsJsonArrays() throws Exception { TestPOJO testPOJO new TestPOJO(); testPOJO.setName(myName); char[] counts new char[]{a,b,c,d}; testPOJO.setCounts(counts); ObjectMapper objectMapper new ObjectMapper(); objectMapper.configure(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS,false); String jsonStr1 objectMapper.writeValueAsString(testPOJO); Assert.assertEquals({\name\:\myName\,\counts\:\abcd\},jsonStr1); ObjectMapper objectMapper2 new ObjectMapper(); objectMapper2.configure(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS,true); String jsonStr2 objectMapper2.writeValueAsString(testPOJO); Assert.assertEquals({\name\:\myName\,\counts\:[\a\,\b\,\c\,\d\]},jsonStr2); } public static class TestPOJO{ private String name; private char[] counts; //getters、setters省略 } SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN序列化BigDecimal时之间输出原始数字还是科学计数默认false即是否以toPlainString()科学计数方式来输出 [java] view plain copy objectMapper.configure(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS,true); 举例 [java] view plain copy Test public void bigDecimalAsPlain() throws Exception { TestPOJO testPOJO new TestPOJO(); testPOJO.setName(myName); testPOJO.setCount(new BigDecimal(1e20)); ObjectMapper objectMapper new ObjectMapper(); objectMapper.configure(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN,false); String jsonStr1 objectMapper.writeValueAsString(testPOJO); Assert.assertEquals({\name\:\myName\,\count\:1E20},jsonStr1); ObjectMapper objectMapper2 new ObjectMapper(); objectMapper2.configure(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN,true); String jsonStr2 objectMapper2.writeValueAsString(testPOJO); Assert.assertEquals({\name\:\myName\,\count\:100000000000000000000},jsonStr2); } 更多的序列化配置参见点击打开链接 配置DeserializationFeature
反序列化的配置这里不再多做解释参见点击打开链接
需要注意的是对于第二种通过配置SerializationConfig和DeserializationConfig方式只能启动/禁止自动检测无法修改我们所需的可见级别
有时候对每个实例进行可见级别的注解可能会非常麻烦这时候我们需要配置一个全局的可见级别通过objectMapper.setVisibilityChecker()来实现默认的VisibilityChecker实现类为VisibilityChecker.Std这样可以满足实现复杂场景下的基础配置。
也有一些实用简单的可见级别配置比如 [java] view plain copy ObjectMapper objectMapper new ObjectMapper(); objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY) // auto-detect all member fields .setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE) // but only public getters .setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE) // and none of is-setters ; 你也可以通过下面方式来禁止所有的自动检测功能 [java] view plain copy ObjectMapper objectMapper new ObjectMapper(); objectMapper.setVisibilityChecker(objectMapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE)); jackson的常用注解 1、JsonAutoDetect
看上面自动检测不再重复
2、JsonIgnore
作用在字段或方法上用来完全忽略被注解的字段和方法对应的属性即便这个字段或方法可以被自动检测到或者还有其他的注解
举例 [java] view plain copy Test public void jsonIgnoreTest() throws Exception { TestPOJO testPOJO new TestPOJO(); testPOJO.setId(111); testPOJO.setName(myName); testPOJO.setCount(22); ObjectMapper objectMapper new ObjectMapper(); String jsonStr objectMapper.writeValueAsString(testPOJO); Assert.assertEquals({\id\:111},jsonStr); String jsonStr2 {\id\:111,\name\:\myName\,\count\:22}; TestPOJO testPOJO2 objectMapper.readValue(jsonStr2, TestPOJO.class); Assert.assertEquals(111,testPOJO2.getId()); Assert.assertNull(testPOJO2.getName()); Assert.assertEquals(0,testPOJO2.getCount()); } public static class TestPOJO{ private int id; JsonIgnore private String name; private int count; public int getId() { return id; } public void setId(int id) { this.id id; } public String getName() { return name; } public void setName(String name) { this.name name; } public int getCount() { return count; } JsonIgnore public void setCount(int count) { this.count count; } } 当JsonIgnore不管注解在getters上还是setters上都会忽略对应的属性 3、JsonProperty 作用在字段或方法上用来对属性的序列化/反序列化可以用来避免遗漏属性同时提供对属性名称重命名比如在很多场景下Java对象的属性是按照规范的驼峰书写但是实际展示的却是类似C-style或C/Microsolft style
举例 [java] view plain copy Test public void jsonPropertyTest() throws Exception { TestPOJO testPOJO new TestPOJO(); testPOJO.wahaha(111); testPOJO.setFirstName(myName); ObjectMapper objectMapper new ObjectMapper(); String jsonStr objectMapper.writeValueAsString(testPOJO); Assert.assertEquals({\id\:111,\first_name\:\myName\},jsonStr); String jsonStr2 {\id\:111,\first_name\:\myName\}; TestPOJO testPOJO2 objectMapper.readValue(jsonStr2, TestPOJO.class); Assert.assertEquals(111, testPOJO2.wahaha()); Assert.assertEquals(myName, testPOJO2.getFirstName()); } public static class TestPOJO{ JsonProperty//注意这里必须得有该注解因为没有提供对应的getId和setId函数而是其他的getter和setter防止遗漏该属性 private int id; JsonProperty(first_name) private String firstName; public int wahaha() { return id; } public void wahaha(int id) { this.id id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName firstName; } } 4、JsonIgnoreProperties 作用在类上用来说明有些属性在序列化/反序列化时需要忽略掉可以将它看做是JsonIgnore的批量操作但它的功能比JsonIgnore要强比如一个类是代理类我们无法将将JsonIgnore标记在属性或方法上此时便可用JsonIgnoreProperties标注在类声明上它还有一个重要的功能是作用在反序列化时解析字段时过滤一些未知的属性否则通常情况下解析到我们定义的类不认识的属性便会抛出异常。
可以注明是想要忽略的属性列表如JsonIgnoreProperties({name,age,title})
也可以注明过滤掉未知的属性如JsonIgnoreProperties(ignoreUnknowntrue)
举例 [java] view plain copy Test(expected UnrecognizedPropertyException.class) public void JsonIgnoreProperties() throws Exception { TestPOJO testPOJO new TestPOJO(); testPOJO.setId(111); testPOJO.setName(myName); testPOJO.setAge(22); ObjectMapper objectMapper new ObjectMapper(); String jsonStr objectMapper.writeValueAsString(testPOJO); Assert.assertEquals({\id\:111},jsonStr);//name和age被忽略掉了 String jsonStr2 {\id\:111,\name\:\myName\,\age\:22,\title\:\myTitle\}; TestPOJO testPOJO2 objectMapper.readValue(jsonStr2, TestPOJO.class); Assert.assertEquals(111, testPOJO2.getId()); Assert.assertNull(testPOJO2.getName()); Assert.assertEquals(0,testPOJO2.getAge()); String jsonStr3 {\id\:111,\name\:\myName\,\count\:33};//这里有个未知的count属性反序列化会报错 objectMapper.readValue(jsonStr3, TestPOJO.class); } JsonIgnoreProperties({name,age,title}) public static class TestPOJO{ private int id; private String name; private int age; //getters、setters省略 } 如果将上面的 [java] view plain copy JsonIgnoreProperties({name,age,title}) 更换为 [java] view plain copy JsonIgnoreProperties(ignoreUnknowntrue) 那么测试用例中在反序列化未知的count属性时便不会抛出异常了 5、JsonUnwrapped
作用在属性字段或方法上用来将子JSON对象的属性添加到封闭的JSON对象说起来比较难懂看个例子就很清楚了不多解释
举例 [java] view plain copy Test public void jsonUnwrapped() throws Exception { TestPOJO testPOJO new TestPOJO(); testPOJO.setId(111); TestName testName new TestName(); testName.setFirstName(张); testName.setSecondName(三); testPOJO.setName(testName); ObjectMapper objectMapper new ObjectMapper(); String jsonStr objectMapper.writeValueAsString(testPOJO); //如果没有JsonUnwrapped序列化后将为{id:111,name:{firstName:张,secondName:三}} //因为在name属性上加了JsonUnwrapped所以name的子属性firstName和secondName将不会包含在name中。 Assert.assertEquals({\id\:111,\firstName\:\张\,\secondName\:\三\},jsonStr); String jsonStr2 {\id\:111,\firstName\:\张\,\secondName\:\三\}; TestPOJO testPOJO2 objectMapper.readValue(jsonStr2,TestPOJO.class); Assert.assertEquals(111,testPOJO2.getId()); Assert.assertEquals(张,testPOJO2.getName().getFirstName()); Assert.assertEquals(三,testPOJO2.getName().getSecondName()); } public static class TestPOJO{ private int id; JsonUnwrapped private TestName name; //getters、setters省略 } public static class TestName{ private String firstName; private String secondName; //getters、setters省略 } 在2.0版本中JsonUnwrapped添加了prefix和suffix属性用来对字段添加前后缀这在有关属性分组上比较有用在上面的测试用例中如果我们将TestPOJO的name属性上的JsonUnwrapped添加前后缀配置即 [java] view plain copy JsonUnwrapped(prefix name_,suffix _test) 那么TestPOJO序列化后将为{id:111,name_firstName_test:张,name_secondName_test:三}反序列化时也要加上前后缀才会被解析为POJO 6、JsonIdentityInfo
2.0版本新注解作用于类或属性上被用来在序列化/反序列化时为该对象或字段添加一个对象识别码通常是用来解决循环嵌套的问题比如数据库中的多对多关系通过配置属性generator来确定识别码生成的方式有简单的配置属性property来确定识别码的名称识别码名称没有限制。 对象识别码可以是虚拟的即存在在JSON中但不是POJO的一部分这种情况下我们可以如此使用注解 [java] view plain copy JsonIdentityInfo(generator ObjectIdGenerators.IntSequenceGenerator.class,property id) 对象识别码也可以是真实存在的即以对象的属性为识别码通常这种情况下我们一般以id属性为识别码可以这么使用注解 [java] view plain copy JsonIdentityInfo(generator ObjectIdGenerators.PropertyGenerator.class,property id) 举例 [java] view plain copy Test public void jsonIdentityInfo() throws Exception { Parent parent new Parent(); parent.setName(jack); Child child new Child(); child.setName(mike); Child[] children new Child[]{child}; parent.setChildren(children); child.setParent(parent); ObjectMapper objectMapper new ObjectMapper(); String jsonStr objectMapper.writeValueAsString(parent); Assert.assertEquals({\id\:1,\name\:\jack\,\children\:[{\name\:\mike\,\parent\:1}]},jsonStr); } JsonIdentityInfo(generator ObjectIdGenerators.IntSequenceGenerator.class,property id) public static class Parent{ private String name; private Child[] children; //getters、setters省略 } public static class Child{ private String name; private Parent parent; //getters、setters省略 } 这里需要提醒一下的是在1.6版本中提供了JsonManagedReference和JsonBackReference来解决循环嵌套问题因为属于过时注解这里就不解释了有兴趣的可以自己看
7、JsonNaming
jackson 2.1版本的注解作用于类或方法注意这个注解是在jackson-databind包中而不是在jackson-annotations包里它可以让你定制属性命名策略作用和前面提到的JsonProperty的重命名属性名称相同。比如 你有一个JSON串{in_reply_to_user_id:abc123}需要反序列化为POJOPOJO一般情况下则需要如此写 [java] view plain copy public static class TestPOJO{ private String in_reply_to_user_id; public String getIn_reply_to_user_id() { return in_reply_to_user_id; } public void setIn_reply_to_user_id(String in_reply_to_user_id) { this.in_reply_to_user_id in_reply_to_user_id; } } 但这显然不符合JAVA的编码规范你可以用JsonProperty比如 [java] view plain copy public static class TestPOJO{ JsonProperty(in_reply_to_user_id) private String inReplyToUserId; public String getInReplyToUserId() { return inReplyToUserId; } public void setInReplyToUserId(String inReplyToUserId) { this.inReplyToUserId inReplyToUserId; } } 这样就符合规范了可是如果POJO里有很多属性给每个属性都要加上JsonProperty是多么繁重的工作这里就需要用到JsonNaming了它不仅能制定统一的命名规则还能任意按自己想要的方式定制 举例 [java] view plain copy Test public void jsonNaming() throws Exception{ String jsonStr {\in_reply_to_user_id\:\abc123\}; ObjectMapper objectMapper new ObjectMapper(); TestPOJO testPOJO objectMapper.readValue(jsonStr,TestPOJO.class); Assert.assertEquals(abc123,testPOJO.getInReplyToUserId()); TestPOJO testPOJO2 new TestPOJO(); testPOJO2.setInReplyToUserId(abc123); String jsonStr2 objectMapper.writeValueAsString(testPOJO2); Assert.assertEquals(jsonStr,jsonStr2); } JsonNaming(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class) public static class TestPOJO{ private String inReplyToUserId; public String getInReplyToUserId() { return inReplyToUserId; } public void setInReplyToUserId(String inReplyToUserId) { this.inReplyToUserId inReplyToUserId; } } JsonNaming使用了jackson已经实现的PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy它可以将大写转换为小写并添加下划线。你可以自定义必须继承类PropertyNamingStrategy建议继承PropertyNamingStrategyBase我们自己实现一个类似LowerCaseWithUnderscoresStrategy的策略只是将下划线改为破折号 举例 [java] view plain copy Test public void jsonNaming() throws Exception{ String jsonStr {\in-reply-to-user-id\:\abc123\}; ObjectMapper objectMapper new ObjectMapper(); TestPOJO testPOJO objectMapper.readValue(jsonStr,TestPOJO.class); Assert.assertEquals(abc123, testPOJO.getInReplyToUserId()); TestPOJO testPOJO2 new TestPOJO(); testPOJO2.setInReplyToUserId(abc123); String jsonStr2 objectMapper.writeValueAsString(testPOJO2); Assert.assertEquals(jsonStr, jsonStr2); } JsonNaming(MyPropertyNamingStrategy.class) public static class TestPOJO{ private String inReplyToUserId; public String getInReplyToUserId() { return inReplyToUserId; } public void setInReplyToUserId(String inReplyToUserId) { this.inReplyToUserId inReplyToUserId; } } public static class MyPropertyNamingStrategy extends PropertyNamingStrategy.PropertyNamingStrategyBase { Override public String translate(String input) { if (input null) return input; // garbage in, garbage out int length input.length(); StringBuilder result new StringBuilder(length * 2); int resultLength 0; boolean wasPrevTranslated false; for (int i 0; i length; i) { char c input.charAt(i); if (i 0 || c ! -) // skip first starting underscore { if (Character.isUpperCase(c)) { if (!wasPrevTranslated resultLength 0 result.charAt(resultLength - 1) ! -) { result.append(-); resultLength; } c Character.toLowerCase(c); wasPrevTranslated true; } else { wasPrevTranslated false; } result.append(c); resultLength; } } return resultLength 0 ? result.toString() : input; } } 如果你想让自己定制的策略对所有解析都实现除了对每个具体的实体类对应的位置加上JsonNaming外你还可以如下做全局配置 [java] view plain copy ObjectMapper objectMapper new ObjectMapper(); objectMapper.setPropertyNamingStrategy(new MyPropertyNamingStrategy()); 多态类型处理 jackson允许配置多态类型处理当进行反序列话时JSON数据匹配的对象可能有多个子类型为了正确的读取对象的类型我们需要添加一些类型信息。可以通过下面几个注解来实现
JsonTypeInfo
作用于类/接口被用来开启多态类型处理对基类/接口和子类/实现类都有效 [java] view plain copy JsonTypeInfo(use JsonTypeInfo.Id.NAME,include JsonTypeInfo.As.PROPERTY,property name) 这个注解有一些属性 use:定义使用哪一种类型识别码它有下面几个可选值
1、JsonTypeInfo.Id.CLASS使用完全限定类名做识别
2、JsonTypeInfo.Id.MINIMAL_CLASS若基类和子类在同一包类使用类名(忽略包名)作为识别码
3、JsonTypeInfo.Id.NAME一个合乎逻辑的指定名称
4、JsonTypeInfo.Id.CUSTOM自定义识别码由JsonTypeIdResolver对应稍后解释
5、JsonTypeInfo.Id.NONE不使用识别码
include(可选):指定识别码是如何被包含进去的它有下面几个可选值
1、JsonTypeInfo.As.PROPERTY作为数据的兄弟属性
2、JsonTypeInfo.As.EXISTING_PROPERTY作为POJO中已经存在的属性
3、JsonTypeInfo.As.EXTERNAL_PROPERTY作为扩展属性
4、JsonTypeInfo.As.WRAPPER_OBJECT作为一个包装的对象
5、JsonTypeInfo.As.WRAPPER_ARRAY作为一个包装的数组
property(可选):制定识别码的属性名称
此属性只有当use为JsonTypeInfo.Id.CLASS若不指定property则默认为class、JsonTypeInfo.Id.MINIMAL_CLASS(若不指定property则默认为c)、JsonTypeInfo.Id.NAME(若不指定property默认为type)include为JsonTypeInfo.As.PROPERTY、JsonTypeInfo.As.EXISTING_PROPERTY、JsonTypeInfo.As.EXTERNAL_PROPERTY时才有效
defaultImpl(可选)如果类型识别码不存在或者无效可以使用该属性来制定反序列化时使用的默认类型
visible(可选默认为false)是否可见
属性定义了类型标识符的值是否会通过JSON流成为反序列化器的一部分默认为fale,也就是说,jackson会从JSON内容中处理和删除类型标识符再传递给JsonDeserializer。 JsonSubTypes
作用于类/接口用来列出给定类的子类只有当子类类型无法被检测到时才会使用它 一般是配合JsonTypeInfo在基类上使用比如 [java] view plain copy JsonTypeInfo(use JsonTypeInfo.Id.NAME,include JsonTypeInfo.As.PROPERTY,property typeName) JsonSubTypes({JsonSubTypes.Type(valueSub1.class,name sub1),JsonSubTypes.Type(valueSub2.class,name sub2)}) JsonSubTypes的值是一个JsonSubTypes.Type[]数组里面枚举了多态类型(value对应类)和类型的标识符值(name对应JsonTypeInfo中的property标识名称的值此为可选值若不制定需由JsonTypeName在子类上制定) JsonTypeName
作用于子类用来为多态子类指定类型标识符的值
比如 [java] view plain copy JsonTypeName(value sub1) value属性作用同上面JsonSubTypes里的name作用 JsonTypeResolver和JsonTypeIdResoler 作用于类可以自定义多态的类型标识符这个平时很少用到主要是现有的一般就已经满足绝大多数的需求了如果你需要比较特别的类型标识符建议使用这2个注解自己定制基于TypeResolverBuilder和TypeIdResolver的类即可
我们看几个jackson处理多态的例子 [java] view plain copy Test public void jsonTypeInfo() throws Exception{ Sub1 sub1 new Sub1(); sub1.setId(1); sub1.setName(sub1Name); Sub2 sub2 new Sub2(); sub2.setId(2); sub2.setAge(33); ObjectMapper objectMapper new ObjectMapper(); TestPOJO testPOJO new TestPOJO(); testPOJO.setMyIns(new MyIn[]{sub1, sub2}); String jsonStr objectMapper.writeValueAsString(testPOJO); Assert.assertEquals({\myIns\:[{\id\:1,\name\:\sub1Name\},{\id\:2,\age\:33}]}, jsonStr); System.out.println(jsonStr); } public static abstract class MyIn{ private int id; //getters、setters省略 } public static class Sub1 extends MyIn{ private String name; //getters、setters省略 } public static class Sub2 extends MyIn{ private int age; //getters、setters省略 } 这是序列化时最简单的一种多态处理方式因为没有使用任何多态处理注解即默认使用的识别码类型为JsonTypeInfo.Id.NONE而jackson没有自动搜索功能所以只能序列化而不能反序列化上面序列化测试的结果为{myIns:[{id:1,name:sub1Name},{id:2,age:33}]}我们可以看到JSON串中是没有对应的多态类型识别码的。 下面我们在基类MyIn上加上多态处理相关注解首先我们在基类MyIn上添加JsonTypeInfo(use JsonTypeInfo.Id.CLASS)即 [java] view plain copy JsonTypeInfo(use JsonTypeInfo.Id.CLASS) public static abstract class MyIn{ private int id; //getters、setters省略 } 执行上面的序列化测试代码结果将会是 {myIns:[{class:cn.yangyong.fodder.util.JacksonUtilsTest$Sub1,id:1,name:sub1Name},{class:cn.yangyong.fodder.util.JacksonUtilsTest$Sub2,id:2,age:33}]}
我们可以看到多了相应的多态类型识别码识别码名称为默认的class因为没有指定名称识别码的值为JsonTypeInfo.Id.CLASS即子类完全限定名
我们再添加上property属性JsonTypeInfo(use JsonTypeInfo.Id.CLASS,property typeName)即 [java] view plain copy JsonTypeInfo(use JsonTypeInfo.Id.CLASS,property typeName) public static abstract class MyIn{ private int id; //getters、setters省略 } 再次执行上面的序列化测试代码结果将会是 {myIns:[{typeName:cn.yangyong.fodder.util.JacksonUtilsTest$Sub1,id:1,name:sub1Name},{typeName:cn.yangyong.fodder.util.JacksonUtilsTest$Sub2,id:2,age:33}]}
这次多态类型识别码的名称已经变成了我们指定的typeName而不是默认的class了
上面的例子都是默认选择的include为JsonTypeInfo.As.PROPERTY下面我们更改include方式看看有什么变化将include设置为JsonTypeInfo.As.WRAPPER_OBJECT即 [java] view plain copy JsonTypeInfo(use JsonTypeInfo.Id.CLASS,include JsonTypeInfo.As.WRAPPER_OBJECT,property typeName) public static abstract class MyIn{ private int id; //getters、setters省略 } 再次执行序列化测试结果为 {myIns:[{cn.yangyong.fodder.util.JacksonUtilsTest$Sub1:{id:1,name:sub1Name}},{cn.yangyong.fodder.util.JacksonUtilsTest$Sub2:{id:2,age:33}}]}
我们看到类型识别码不再成为兄弟属性包含进去了而是为父属性将其他属性包含进去此时我们指定的property“typeName”已经无用了
再次修改use属性指定为JsonTypeInfo.Id.MINIMAL_CLASS即JsonTypeInfo(use JsonTypeInfo.Id.MINIMAL_CLASS,include JsonTypeInfo.As.PROPERTY,property typeName) [java] view plain copy JsonTypeInfo(use JsonTypeInfo.Id.MINIMAL_CLASS,include JsonTypeInfo.As.PROPERTY,property typeName) public static abstract class MyIn{ private int id; //getters、setters省略 } 测试序列化结果为 {myIns:[{typeName:.JacksonUtilsTest$Sub1,id:1,name:sub1Name},{typeName:.JacksonUtilsTest$Sub2,id:2,age:33}]}
发现已经没有同包的package名称识别码的值更加简短了
测试反序列化 [java] view plain copy Test public void jsonTypeInfo() throws Exception{ ObjectMapper objectMapper new ObjectMapper(); String jsonStr2 {\myIns\:[{\typeName\:\.JacksonUtilsTest$Sub1\,\id\:1,\name\:\sub1Name\},{\typeName\:\.JacksonUtilsTest$Sub2\,\id\:2,\age\:33}]}; TestPOJO testPOJO2 objectMapper.readValue(jsonStr2,TestPOJO.class); MyIn[] myIns testPOJO2.getMyIns(); for (MyIn myIn : myIns) { System.out.println(myIn.getClass().getSimpleName()); } } 结果将会显示为Sub1和Sub2说明是可以实现多态的反序列化的 可能我们在反序列化时觉得如此传递识别码很不友好最好可以自定义识别码的值可以选择use JsonTypeInfo.Id.NAME和JsonSubTypes配合即 [java] view plain copy JsonTypeInfo(use JsonTypeInfo.Id.NAME,include JsonTypeInfo.As.PROPERTY,property typeName) JsonSubTypes({JsonSubTypes.Type(valueSub1.class,namesub1),JsonSubTypes.Type(valueSub2.class,namesub2)}) public static abstract class MyIn{ private int id; //getters、setters省略 } 执行序列化结果为 {myIns:[{typeName:sub1,id:1,name:sub1Name},{typeName:sub2,id:2,age:33}]}
使用这个结果反序列化也可以得到我们想要的结果或者在子类上添加JsonTypeName(value sub1)和JsonTypeName(value sub2)以便取代JsonSubTypes里的name
如果想不使用JsonSubTypes来实现反序列化我们可以在ObjectMapper上注册子类实现即 [java] view plain copy ObjectMapper objectMapper new ObjectMapper(); objectMapper.registerSubtypes(new NamedType(Sub1.class,sub1)); objectMapper.registerSubtypes(new NamedType(Sub2.class,sub2)); 更多多态处理的例子还请大家自己研究 用于序列化和反序列化的注解类
1、JsonSerialize和JsonDeserialize
作用于方法和字段上通过 using(JsonSerializer)和using(JsonDeserializer)来指定序列化和反序列化的实现通常我们在需要自定义序列化和反序列化时会用到比如下面的例子中的日期转换 [java] view plain copy Test public void jsonSerializeAndDeSerialize() throws Exception { TestPOJO testPOJO new TestPOJO(); testPOJO.setName(myName); testPOJO.setBirthday(new Date()); ObjectMapper objectMapper new ObjectMapper(); String jsonStr objectMapper.writeValueAsString(testPOJO); System.out.println(jsonStr); String jsonStr2 {\name\:\myName\,\birthday\:\2014-11-11 19:01:58\}; TestPOJO testPOJO2 objectMapper.readValue(jsonStr2,TestPOJO.class); System.out.println(testPOJO2.toString()); } public static class TestPOJO{ private String name; JsonSerialize(using MyDateSerializer.class) JsonDeserialize(using MyDateDeserializer.class) private Date birthday; //getters、setters省略 Override public String toString() { return TestPOJO{ name name \ , birthday birthday }; } } private static class MyDateSerializer extends JsonSerializerDate{ Override public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { DateFormat dateFormat new SimpleDateFormat(yyyy-MM-dd HH:mm:ss); String dateStr dateFormat.format(value); jgen.writeString(dateStr); } } private static class MyDateDeserializer extends JsonDeserializerDate{ Override public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { String value jp.getValueAsString(); DateFormat dateFormat new SimpleDateFormat(yyyy-MM-dd HH:mm:ss); try { return dateFormat.parse(value); } catch (ParseException e) { e.printStackTrace(); } return null; } } 上面的例子中自定义了日期的序列化和反序列化方式可以将Date和指定日期格式字符串之间相互转换。也可以通过使用as(JsonSerializer)和as(JsonDeserializer)来实现多态类型转换上面我们有提到多态类型处理时可以使用JsonTypeInfo实现还有一种比较简便的方式就是使用JsonSerialize和JsonDeserialize指定as的子类类型注意这里必须指定为子类类型才可以实现替换运行时的类型 [java] view plain copy Test public void jsonSerializeAndDeSerialize() throws Exception { TestPOJO testPOJO new TestPOJO(); testPOJO.setName(myName); Sub1 sub1 new Sub1(); sub1.setId(1); sub1.setName(sub1Name); Sub2 sub2 new Sub2(); sub2.setId(2); sub2.setAge(22); testPOJO.setSub1(sub1); testPOJO.setSub2(sub2); ObjectMapper objectMapper new ObjectMapper(); String jsonStr objectMapper.writeValueAsString(testPOJO); System.out.println(jsonStr); String jsonStr2 {\name\:\myName\,\sub1\:{\id\:1,\name\:\sub1Name\},\sub2\:{\id\:2,\age\:22}}; TestPOJO testPOJO2 objectMapper.readValue(jsonStr2,TestPOJO.class); System.out.println(testPOJO2.toString()); } public static class TestPOJO{ private String name; JsonSerialize(as Sub1.class) JsonDeserialize(as Sub1.class) private MyIn sub1; JsonSerialize(as Sub2.class) JsonDeserialize(as Sub2.class) private MyIn sub2; //getters、setters省略 Override public String toString() { return TestPOJO{ name name \ , sub1 sub1 , sub2 sub2 }; } } public static class MyIn{ private int id; //getters、setters省略 } public static class Sub1 extends MyIn{ private String name; //getters、setters省略 Override public String toString() { return Sub1{ id getId() name name \ }; } } public static class Sub2 extends MyIn{ private int age; //getters、setters省略 Override public String toString() { return Sub1{ id getId() age age }; } } 上面例子中通过as来指定了需要替换实际运行时类型的子类实际上上面例子中序列化时是可以不使用JsonSerialize(as Sub1.class)的因为jackson可以自动将POJO转换为对应的JSON而反序列化时由于无法自动检索匹配类型必须要指定JsonDeserialize(as Sub1.class)方可实现 最后JsonSerialize可以配置include属性来指定序列化时被注解的属性被包含的方式默认总是被包含进来但是可以过滤掉空的属性或有默认值的属性举个简单的过滤空属性的例子如下 [java] view plain copy Test public void jsonSerializeAndDeSerialize() throws Exception { TestPOJO testPOJO new TestPOJO(); testPOJO.setName(); ObjectMapper objectMapper new ObjectMapper(); String jsonStr objectMapper.writeValueAsString(testPOJO); Assert.assertEquals({},jsonStr); } public static class TestPOJO{ JsonSerialize(include JsonSerialize.Inclusion.NON_EMPTY) private String name; //getters、setters省略 } 2、JsonPropertyOrder
作用在类上被用来指明当序列化时需要对属性做排序它有2个属性 一个是alphabetic布尔类型表示是否采用字母拼音顺序排序默认是为false即不排序 [java] view plain copy Test public void jsonPropertyOrder() throws Exception { TestPOJO testPOJO new TestPOJO(); testPOJO.setA(1); testPOJO.setB(2); testPOJO.setC(3); testPOJO.setD(4); ObjectMapper objectMapper new ObjectMapper(); String jsonStr objectMapper.writeValueAsString(testPOJO); Assert.assertEquals({\a\:\1\,\c\:\3\,\d\:\4\,\b\:\2\},jsonStr); } public static class TestPOJO{ private String a; private String c; private String d; private String b; //getters、setters省略 } 我们先看一个默认的排序方式序列化单元测试结果依次为{a:1,c:3,d:4,b:2}即是没有经过排序操作的在TestPOJO上加上jsonPropertyOrder(alphabetic true)再执行测试结果将会为{a:1,b:2,c:3,d:4}还有一个属性是value数组类型表示将优先其他属性排序的属性名称 [java] view plain copy Test public void jsonPropertyOrder() throws Exception { TestPOJO testPOJO new TestPOJO(); testPOJO.setA(1); testPOJO.setB(2); testPOJO.setC(3); testPOJO.setD(4); ObjectMapper objectMapper new ObjectMapper(); String jsonStr objectMapper.writeValueAsString(testPOJO); System.out.println(jsonStr); Assert.assertEquals({\c\:\3\,\b\:\2\,\a\:\1\,\d\:\4\},jsonStr); } JsonPropertyOrder(alphabetic true,value {c,b}) public static class TestPOJO{ private String a; private String c; private String d; private String b; //getters、setters省略 } 上面例子可以看到value指定了c和b属性优先排序所以序列化后为{c:3,b:2,a:1,d:4} 还记得本文上面最开始配置MapperFeature时也有属性排序么对就是 [java] view plain copy objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY,true); 只不过JsonPropertyOrder颗粒度要更细一点可以决定哪些属性优先排序 3、JsonView
视图模板作用于方法和属性上用来指定哪些属性可以被包含在JSON视图中在前面我们知道已经有JsonIgnore和JsonIgnoreProperties可以排除过滤掉不需要序列化的属性可是如果一个POJO中有上百个属性比如订单类、商品详情类这种属性超多而我们可能只需要概要简单信息即序列化时只想输出其中几个或10几个属性此时使用JsonIgnore和JsonIgnoreProperties就显得非常繁琐而使用JsonView便会非常方便只许在你想要输出的属性(或对应的getter)上添加JsonView即可举例 [java] view plain copy Test public void jsonView() throws Exception { TestPOJO testPOJO new TestPOJO(); testPOJO.setA(1); testPOJO.setB(2); testPOJO.setC(3); testPOJO.setD(4); ObjectMapper objectMapper new ObjectMapper(); objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false); String jsonStr objectMapper.writerWithView(FilterView.OutputA.class).writeValueAsString(testPOJO); Assert.assertEquals({\a\:\1\,\c\:\3\},jsonStr); String jsonStr2 objectMapper.writerWithView(FilterView.OutputB.class).writeValueAsString(testPOJO); Assert.assertEquals({\d\:\4\,\b\:\2\},jsonStr2); } public static class TestPOJO{ JsonView(FilterView.OutputA.class) private String a; JsonView(FilterView.OutputA.class) private String c; JsonView(FilterView.OutputB.class) private String d; JsonView(FilterView.OutputB.class) private String b; //getters、setters忽略 } private static class FilterView { static class OutputA {} static class OutputB {} } 上面的测试用例中我们在序列化之前先设置了objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false)看javadoc说这是一个双向开关开启将输出没有JsonView注解的属性false关闭将输出有JsonView注解的属性可惜我在测试中开启开关后有JsonView注解的属性任然输出了大家可以研究下。序列化时使用了objectMapper.writerWithView(FilterView.OutputA.class).writeValueAsString(testPOJO)即使用哪个视图来输出。在上面的例子中又2种视图我们在序列化的时候可以选择想要的视图来输出这在一些地方比较好用比如安卓、苹果、桌面等不同的客户端可能会输出不同的属性。在1.6版本中这个JsonView注解同时也会强制性自动发现也就是说不管属性的可见性以及是否设置了自动发现这些属性都将会自动被发现在上例中TestPOJO中的getters、setters可以不需要也能输出我们想要的结果。 4、JsonFilter
Json属性过滤器作用于类作用同上面的JsonView都是过滤掉不想要的属性输出自己想要的属性。和FilterView不同的是JsonFilter可以动态的过滤属性比如我不想输出以system开头的所有属性等待应该说JsonFilter更高级一点举个简单的例子 [java] view plain copy Test public void jsonFilter() throws Exception { TestPOJO testPOJO new TestPOJO(); testPOJO.setA(1); testPOJO.setB(2); testPOJO.setC(3); testPOJO.setD(4); ObjectMapper objectMapper new ObjectMapper(); FilterProvider filters new SimpleFilterProvider().addFilter(myFilter,SimpleBeanPropertyFilter.filterOutAllExcept(a)); objectMapper.setFilters(filters); String jsonStr objectMapper.writeValueAsString(testPOJO); Assert.assertEquals({\a\:\1\},jsonStr); } JsonFilter(myFilter) public static class TestPOJO{ private String a; private String c; private String d; private String b; //getters、setters省略 } 上面例子中在我们想要序列化的POJO上加上了JsonFilter表示该类将使用名为myFilter的过滤器。在测试中定义了一个名为myFilter的SimpleFilterProvider这个过滤器将会过滤掉所有除a属性以外的属性。这只是最简单的输出指定元素的例子你可以自己实现FilterProvider来满足你的过滤需求。 有时候我们可能需要根据现有的POJO来过滤属性而这种情况下通常不会让你修改已有的代码在POJO上加注解这种情况下我们就可以结合JsonFilter和MixInAnnotations来实现过滤属性如下例所示不再多做解释 [java] view plain copy Test public void jsonFilter() throws Exception { TestPOJO testPOJO new TestPOJO(); testPOJO.setA(1); testPOJO.setB(2); testPOJO.setC(3); testPOJO.setD(4); ObjectMapper objectMapper new ObjectMapper(); FilterProvider filters new SimpleFilterProvider().addFilter(myFilter,SimpleBeanPropertyFilter.filterOutAllExcept(a)); objectMapper.setFilters(filters); objectMapper.addMixInAnnotations(TestPOJO.class,MyFilterMixIn.class); String jsonStr objectMapper.writeValueAsString(testPOJO); Assert.assertEquals({\a\:\1\},jsonStr); } public static class TestPOJO{ private String a; private String c; private String d; private String b; //getters、setters省略 } JsonFilter(myFilter) private static interface MyFilterMixIn{ } 5、JsonIgnoreType
作用于类表示被注解该类型的属性将不会被序列化和反序列化也跟上面几个一样属于过滤属性功能的注解举例 [java] view plain copy Test public void jsonFilter() throws Exception { TestPOJO testPOJO new TestPOJO(); testPOJO.setName(myName); Sub1 sub1 new Sub1(); sub1.setId(1); sub1.setName(sub1); Sub2 sub2 new Sub2(); sub2.setId(2); sub2.setAge(22); testPOJO.setMyIn(sub1); testPOJO.setSub1(sub1); testPOJO.setSub2(sub2); ObjectMapper objectMapper new ObjectMapper(); String jsonStr objectMapper.writeValueAsString(testPOJO); System.out.println(jsonStr); } public static class TestPOJO{ private Sub1 sub1; private Sub2 sub2; private MyIn myIn; private String name; //getters、setters省略 } public static class MyIn{ private int id; //getters、setters省略 } JsonIgnoreType public static class Sub1 extends MyIn{ private String name; //getters、setters省略 } JsonIgnoreType public static class Sub2 extends MyIn{ private int age; //getters、setters省略 } 上面例子中我们在类Sub1和Sub2上都加上了JsonIgnoreType那么需要序列化和反序列时POJO中所有Sub1和Sub2类型的属性都将会被忽略上面测试结果为{myIn:{id:1,name:sub1},name:myName}只输出了name和myIn属性。需要注意的是JsonIgnoreType是可以继承的即如果在基类上添加了该注解那么子类也相当于加了该注解。在上例中如果只在基类MyIn上添加JsonIgnoreType那么序列化TestPOJO时将会过滤掉MyIn、Sub1、Sub2。输出结果为{name:myName} 6、JsonAnySetter
作用于方法在反序列化时用来处理遇到未知的属性的时候调用在本文前面我们知道可以通过注解JsonIgnoreProperties(ignoreUnknowntrue)来过滤未知的属性但是如果需要这些未知的属性该如何是好?那么JsonAnySetter就可以派上用场了它通常会和map属性配合使用用来保存未知的属性举例 [java] view plain copy Test public void jsonAnySetter() throws Exception { ObjectMapper objectMapper new ObjectMapper(); String jsonStr {\name\:\myName\,\code\:\12345\,\age\:12}; TestPOJO testPOJO objectMapper.readValue(jsonStr,TestPOJO.class); Assert.assertEquals(myName,testPOJO.getName()); Assert.assertEquals(12345,testPOJO.getOther().get(code)); Assert.assertEquals(12,testPOJO.getOther().get(age)); } public static class TestPOJO{ private String name; private Map other new HashMap(); JsonAnySetter public void set(String name,Object value) { other.put(name,value); } //getters、setters省略 } 测试用例中我们在set方法上标注了JsonAnySetter每当遇到未知的属性时都会调用该方法 7、JsonCreator 作用于方法通常用来标注构造方法或静态工厂方法上使用该方法来构建实例默认的是使用无参的构造方法通常是和JsonProperty或JacksonInject配合使用举例 [java] view plain copy Test public void jsonCreator() throws Exception { ObjectMapper objectMapper new ObjectMapper(); String jsonStr {\full_name\:\myName\,\age\:12}; TestPOJO testPOJO objectMapper.readValue(jsonStr,TestPOJO.class); Assert.assertEquals(myName,testPOJO.getName()); Assert.assertEquals(12, testPOJO.getAge()); } public static class TestPOJO{ private String name; private int age; JsonCreator public TestPOJO(JsonProperty(full_name) String name,JsonProperty(age) int age){ this.name name; this.age age; } public String getName() { return name; } public int getAge() { return age; } } 上面示例中是在构造方法上标注了JsonCreator同样你也可以标注在静态工厂方法上比如 [java] view plain copy Test public void jsonCreator() throws Exception { ObjectMapper objectMapper new ObjectMapper(); String jsonStr {\name\:\myName\,\birthday\:1416299461556}; TestPOJO testPOJO objectMapper.readValue(jsonStr,TestPOJO.class); Assert.assertEquals(myName,testPOJO.getName()); System.out.println(testPOJO.getBirthday()); } public static class TestPOJO{ private String name; private Date birthday; private TestPOJO(String name,Date birthday){ this.name name; this.birthday birthday; } JsonCreator public static TestPOJO getInstance(JsonProperty(name) String name,JsonProperty(birthday) long timestamp){ Date date new Date(timestamp); return new TestPOJO(name,date); } public String getName() { return name; } public Date getBirthday() { return birthday; } } 这个实例中TestPOJO的构造方法是私有的外面无法new出来该对象只能通过工厂方法getInstance来构造实例此时JsonCreator就标注在工厂方法上。 除了这2种方式外还有一种构造方式成为授权式构造器也是我们平常比较常用到的这个构造器只有一个参数且不能使用JsonProperty。举例 [java] view plain copy Test public void jsonCreator() throws Exception { ObjectMapper objectMapper new ObjectMapper(); String jsonStr {\full_name\:\myName\,\age\:12}; TestPOJO testPOJO objectMapper.readValue(jsonStr,TestPOJO.class); Assert.assertEquals(myName,testPOJO.getName()); Assert.assertEquals(12,testPOJO.getAge()); } public static class TestPOJO{ private String name; private int age; JsonCreator public TestPOJO(Map map){ this.name (String)map.get(full_name); this.age (Integer)map.get(age); } public String getName() { return name; } public int getAge() { return age; } } 8、JacksonInject
作用于属性、方法、构造参数上被用来反序列化时标记已经被注入的属性举例 [java] view plain copy Test public void jacksonInject() throws Exception { ObjectMapper objectMapper new ObjectMapper(); String jsonStr {\age\:12}; InjectableValues inject new InjectableValues.Std().addValue(name,myName); TestPOJO testPOJO objectMapper.reader(TestPOJO.class).with(inject).readValue(jsonStr); Assert.assertEquals(myName, testPOJO.getName()); Assert.assertEquals(12,testPOJO.getAge()); } public static class TestPOJO{ JacksonInject(name) private String name; private int age; //getters、setters省略 } 上面例子中我们在反序列化前通过InjectableValues来进行注入我们想要的属性 9、JsonPOJOBuilder 作用于类用来标注如何定制构建对象使用的是builder模式来构建比如Value v new ValueBuilder().withX(3).withY(4).build();这种就是builder模式来构建对象通常会喝JsonDeserialize.builder来配合使用我们举个例子 [java] view plain copy Test public void jacksonInject() throws Exception { ObjectMapper objectMapper new ObjectMapper(); String jsonStr {\name\:\myName\,\age\:12}; TestPOJO testPOJO objectMapper.readValue(jsonStr,TestPOJO.class); Assert.assertEquals(myName, testPOJO.getName()); Assert.assertEquals(12,testPOJO.getAge()); } JsonDeserialize(builderTestPOJOBuilder.class) public static class TestPOJO{ private String name; private int age; public TestPOJO(String name, int age) { this.name name; this.age age; } public String getName() { return name; } public int getAge() { return age; } } JsonPOJOBuilder(buildMethodName create,withPrefix with) public static class TestPOJOBuilder{ private String name; private int age; public TestPOJOBuilder withName(String name) { this.name name; return this; } public TestPOJOBuilder withAge(int age) { this.age age; return this; } public TestPOJO create() { return new TestPOJO(name,age); } } 在TestPOJOBuilder上有JsonPOJOBuilder注解表示所有的参数传递方法都是以with开头最终构建好的对象是通过create方法来获得而在TestPOJO上使用了JsonDeserializer告诉我们在反序列化的时候我们使用的是TestPOJOBuilder来构建此对象的 还有一些过期不推荐使用的注解我们一笔带过主要知道他们是跟哪些其他注解功能一样即可 JsonGetter
作用于方法1.0版本开始的注解已经过期不推荐使用改用JsonPropertyJsonUseSerializer
作用于类和方法1.5版本开始被移除了改用JsonSerialize
JsonSetter 作用于方法1.0版本开始的注解已过期不推荐使用改用JsonProperty
JsonClass
作用于方法和类1.9版本开始被移除了改为JsonDeserialize.as
JsonContentClass
作用于方法1.9版本开始被移除了改为JsonDeserialize.contentAs
JsonKeyClass
作用于方法和类1.9版本开始被移除了改为JsonDeserialize.keyAs
JsonUseDeserializer
作用于方法和类1.5版本开始被移除了改为JsonDeserialize