jackson目的是什么呢? 它是解决json和bean之间对应关系,json就是字符和java的bean如何进行关联,json字符和bean之间会有哪些问题呢?
文章目录
- 1、预先思考
- 2、具体jackson注解
- 2.1、@JsonAnySetter
- 2.2、@JsonGetter /@JsonSetter
- 2.3、@JsonPropertyOrder
- 2.4、@JsonRawValue
- 2.5、@JsonValue
- 2.6、@JsonRootName
- 2.7、@JsonSerialize 和@JsonDeserialize
- 2.8、@JsonCreator
- 2.9、@JacksonInject
- 2.10、@JsonAlias
- 2.11、@JsonIgnoreProperties
- 2.12、@JsonIgnore
- 2.13、@JsonIgoreType
- 2.14、@JsonInclude
- 2.15、@JsonAutoDetect
- 2.16、@JsonTypeInfo
- 2.17、@JsonSubTypes
- 2.18、@JsonTypeName
- 2.19、@JsonFormat
- 2.20、@JsonUnwrapped
- 2.21、@JsonView
- 2.22、@JsonManagedReference
- 2.23、@JsonIdentityInfo
- 2.24、@JsonFilter
- 引用
1、预先思考
- 最理想情况下,就json和bean是一一对应,层次结构相同,成员变量和json的key对应字符串相同,这样json也是最好处理。
1.1、json和bean会有什么问题呢?
- 当一个系统与多个系统进行交互的时候采用json格式,不同系统生成json格式层次和json中的key可能不同
- 比如说A系统用户名字段是userName , B系统中用户名字段user_name, 我们系统定义用户名字段userN,这个时候怎么做
- 方案一:对方系统转换成我们系统字段名传给我们
- 方案二:对方已经成熟系统不愿意改,我们系统写一个适配器接收两个系统原始进行转换成标准的(当差异很大时候,这个方式比较合理),如果只是字段名微调就重新定义一个适配器有那个啥?
- 方案三:jackson可以解决这种适配情况(json字段与bean字段一对多的关系)
- json对象的字段不一定,不同场景传递字段不一样且数量不定,比如说订单,比如对接多个快递公司,每个快递公司填信息不一样,传到我们系统时候,有时候这个字段存在,有时它不存在,此时我们怎么定义bean呢?
- 方案一:把所有可能字段全部定义
- 方案二:把可变对象定义成一个字段JsonObject对象之类,其实它本质也就一个map
- 方案三:jackson注解简单解决这个问题,本质上也是map
- json 和枚举关系怎么对应,到底是对应枚举那个属性和枚举本身的name?这个jackson也可以配置
- json 和bean多态怎么对应呢?场景是这样的,就拿订单来说,订单主信息是一样,而明细可以不一样,比如下预售订单和现货订单就不一样?那此时你在想我需要对预售订单和现货订单分别提供接口,如果只提供一个接口怎么实现呢?这个时候需要在解析json时候如何对应不同明细子类呢?jackson也是有这种特性
- 有时候我需要忽略null转成json字符串中,或者说觉得某个字段不需要转成json字符,如何灵活配置忽略字段呢?
- 格式转换,比如说数据库查询出来是10000,我们希望转给前端是$10,000, 或者前端传给我们是$10,000,我们转换成10000,jackson可以定义转换逻辑
- 如果bean出现循环依赖,转成json应该是什么样?怎么解决?
- 带这个问题去了解jackson
2、具体jackson注解
2.1、@JsonAnySetter
-
将Map的属性变成bean的属性,且动态变化的,变成bean属性时,key就是属性名称, value就是属性值。
-
public class ExtendableBean { public String name; private Map<String, String> properties; @JsonAnyGetter public Map<String, String> getProperties() { return properties; } } @Test public void whenSerializingUsingJsonAnyGetter_thenCorrect() throws JsonProcessingException { ExtendableBean bean = new ExtendableBean("My bean"); bean.add("attr1", "val1"); bean.add("attr2", "val2"); String result = new ObjectMapper().writeValueAsString(bean); assertThat(result, containsString("attr1")); assertThat(result, containsString("val1")); } -
输出结果
-
{ "name":"My bean", "attr2":"val2", "attr1":"val1" }
-
2.2、@JsonGetter /@JsonSetter
-
当方法和属性不同时候就可以利用@JsonGetter/@JsonSetter指定某一个属性
-
public class MyBean { public int id; private String name; @JsonGetter("name") public String getTheName() { return name; } } @Test public void whenSerializingUsingJsonGetter_thenCorrect() throws JsonProcessingException { MyBean bean = new MyBean(1, "My bean"); String result = new ObjectMapper().writeValueAsString(bean); assertThat(result, containsString("My bean")); assertThat(result, containsString("1")); }
2.3、@JsonPropertyOrder
-
指定序列化字段顺序,这个场景用的不是很多,@JsonPropertyOrder(alphabetic = true) 表示按照26字母顺序排序
-
@JsonPropertyOrder({ "name", "id" }) public class MyBean { public int id; public String name; } @Test public void whenSerializingUsingJsonPropertyOrder_thenCorrect() throws JsonProcessingException { MyBean bean = new MyBean(1, "My bean"); String result = new ObjectMapper().writeValueAsString(bean); assertThat(result, containsString("My bean")); assertThat(result, containsString("1")); } -
输出结果
-
{ "name":"My bean", "id":1 }
-
2.4、@JsonRawValue
-
过滤某个字段不要jackson进行处理,只适合将bean转换成json字符串,不能用json字符串转成bean
-
public class RawBean { public String name; @JsonRawValue public String json; } @Test public void whenSerializingUsingJsonRawValue_thenCorrect() throws JsonProcessingException { RawBean bean = new RawBean("My bean", "{\"attr\":false}"); String result = new ObjectMapper().writeValueAsString(bean); assertThat(result, containsString("My bean")); assertThat(result, containsString("{\"attr\":false}")); } -
输出结果
-
{ "name":"My bean", "json":{ "attr":false } }
-
2.5、@JsonValue
-
一般用于枚举到达使用哪个值进行序列化,某个实体中只序列化某个方法和成员变量
-
public enum TypeEnumWithValue { TYPE1(1, "Type A"), TYPE2(2, "Type 2"); private Integer id; private String name; // standard constructors @JsonValue public String getName() { return name; } } @Test public void whenSerializingUsingJsonValue_thenCorrect() throws JsonParseException, IOException { String enumAsString = new ObjectMapper() .writeValueAsString(TypeEnumWithValue.TYPE1); assertThat(enumAsString, is(""Type A"")); }
2.6、@JsonRootName
-
需要开启WRAP_ROOT_VALUE开关 ,实例化成json时候套个壳,多加一层
-
@JsonRootName(value = "user")public class UserWithRoot { public int id; public String name;}@Testpublic void whenSerializingUsingJsonRootName_thenCorrect() throws JsonProcessingException { UserWithRoot user = new User(1, "John"); ObjectMapper mapper = new ObjectMapper(); mapper.enable(SerializationFeature.WRAP_ROOT_VALUE); String result = mapper.writeValueAsString(user); assertThat(result, containsString("John")); assertThat(result, containsString("user"));} -
输出结果
-
{ "user":{ "id":1, "name":"John" }}
-
2.7、@JsonSerialize 和@JsonDeserialize
-
自定义序列化和反序列类
-
public class EventWithSerializer { public String name; @JsonSerialize(using = CustomDateSerializer.class) public Date eventDate;}public class CustomDateSerializer extends StdSerializer<Date> { private static SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); public CustomDateSerializer() { this(null); } public CustomDateSerializer(Class<Date> t) { super(t); } @Override public void serialize( Date value, JsonGenerator gen, SerializerProvider arg2) throws IOException, JsonProcessingException { gen.writeString(formatter.format(value)); }}@Testpublic void whenSerializingUsingJsonSerialize_thenCorrect() throws JsonProcessingException, ParseException { SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); String toParse = "20-12-2014 02:30:00"; Date date = df.parse(toParse); EventWithSerializer event = new EventWithSerializer("party", date); String result = new ObjectMapper().writeValueAsString(event); assertThat(result, containsString(toParse));}
2.8、@JsonCreator
-
构造器方法
-
public class BeanWithCreator { public int id; public String name; @JsonCreator public BeanWithCreator( @JsonProperty("id") int id, @JsonProperty("theName") String name) { this.id = id; this.name = name; }}@Testpublic void whenDeserializingUsingJsonCreator_thenCorrect() throws IOException { String json = "{\"id\":1,\"theName\":\"My bean\"}"; BeanWithCreator bean = new ObjectMapper() .readerFor(BeanWithCreator.class) .readValue(json); assertEquals("My bean", bean.name);} -
输出
-
{ "id":1, "theName":"My bean"}
-
2.9、@JacksonInject
-
json字符串没有对应的字段,就需要预先通过注射一个值
-
public class BeanWithInject { @JacksonInject public int id; public String name;}@Testpublic void whenDeserializingUsingJsonInject_thenCorrect() throws IOException { String json = "{\"name\":\"My bean\"}"; InjectableValues inject = new InjectableValues.Std() .addValue(int.class, 1); BeanWithInject bean = new ObjectMapper().reader(inject) .forType(BeanWithInject.class) .readValue(json); assertEquals("My bean", bean.name); assertEquals(1, bean.id);}
2.10、@JsonAlias
-
json多个名称对应一个bean上字段
-
public class AliasBean { @JsonAlias({ "fName", "f_name" }) private String firstName; private String lastName;}@Testpublic void whenDeserializingUsingJsonAlias_thenCorrect() throws IOException { String json = "{\"fName\": \"John\", \"lastName\": \"Green\"}"; AliasBean aliasBean = new ObjectMapper().readerFor(AliasBean.class).readValue(json); assertEquals("John", aliasBean.getFirstName());}
2.11、@JsonIgnoreProperties
-
类级别注解, 忽略某一些字段
-
@JsonIgnoreProperties({ "id" })public class BeanWithIgnore { public int id; public String name;}@Testpublic void whenSerializingUsingJsonIgnoreProperties_thenCorrect() throws JsonProcessingException { BeanWithIgnore bean = new BeanWithIgnore(1, "My bean"); String result = new ObjectMapper() .writeValueAsString(bean); assertThat(result, containsString("My bean")); assertThat(result, not(containsString("id")));}
2.12、@JsonIgnore
-
成员变量的,忽略单个字段
-
public class BeanWithIgnore { @JsonIgnore public int id; public String name;} -
@Testpublic void whenSerializingUsingJsonIgnore_thenCorrect() throws JsonProcessingException { BeanWithIgnore bean = new BeanWithIgnore(1, "My bean"); String result = new ObjectMapper() .writeValueAsString(bean); assertThat(result, containsString("My bean")); assertThat(result, not(containsString("id")));}
2.13、@JsonIgoreType
-
忽略某类型的字段
-
public class User { public int id; public Name name; @JsonIgnoreType public static class Name { public String firstName; public String lastName; }}@Testpublic void whenSerializingUsingJsonIgnoreType_thenCorrect() throws JsonProcessingException, ParseException { User.Name name = new User.Name("John", "Doe"); User user = new User(1, name); String result = new ObjectMapper() .writeValueAsString(user); assertThat(result, containsString("1")); assertThat(result, not(containsString("name"))); assertThat(result, not(containsString("John")));}
2.14、@JsonInclude
-
哪些字段包括在内进行序列化
-
@JsonInclude(Include.NON_NULL)public class MyBean { public int id; public String name;}public void whenSerializingUsingJsonInclude_thenCorrect() throws JsonProcessingException { MyBean bean = new MyBean(1, null); String result = new ObjectMapper() .writeValueAsString(bean); assertThat(result, containsString("1")); assertThat(result, not(containsString("name")));}
2.15、@JsonAutoDetect
-
自动检测,哪些限制修饰符属性可以json序列化
-
@JsonAutoDetect(fieldVisibility = Visibility.ANY)public class PrivateBean { private int id; private String name;}@Testpublic void whenSerializingUsingJsonAutoDetect_thenCorrect() throws JsonProcessingException { PrivateBean bean = new PrivateBean(1, "My bean"); String result = new ObjectMapper() .writeValueAsString(bean); assertThat(result, containsString("1")); assertThat(result, containsString("My bean"));}
2.16、@JsonTypeInfo
-
序列化的详细信息
-
public class Zoo { public Animal animal; @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = As.PROPERTY, property = "type") @JsonSubTypes({ @JsonSubTypes.Type(value = Dog.class, name = "dog"), @JsonSubTypes.Type(value = Cat.class, name = "cat") }) public static class Animal { public String name; } @JsonTypeName("dog") public static class Dog extends Animal { public double barkVolume; } @JsonTypeName("cat") public static class Cat extends Animal { boolean likesCream; public int lives; }}@Testpublic void whenSerializingPolymorphic_thenCorrect() throws JsonProcessingException { Zoo.Dog dog = new Zoo.Dog("lacy"); Zoo zoo = new Zoo(dog); String result = new ObjectMapper() .writeValueAsString(zoo); assertThat(result, containsString("type")); assertThat(result, containsString("dog"));} -
输出
-
{ "animal": { "type": "dog", "name": "lacy", "barkVolume": 0 }}
-
-
反序列化
-
@Testpublic void whenDeserializingPolymorphic_thenCorrect()throws IOException { String json = "{\"animal\":{\"name\":\"lacy\",\"type\":\"cat\"}}"; Zoo zoo = new ObjectMapper() .readerFor(Zoo.class) .readValue(json); assertEquals("lacy", zoo.animal.name); assertEquals(Zoo.Cat.class, zoo.animal.getClass());}
-
2.17、@JsonSubTypes
- 表示子类注解(对应关系)
2.18、@JsonTypeName
- 表示对应值
2.19、@JsonFormat
-
json格式化,一般是日期和字符串之间转换
-
public class EventWithFormat { public String name; @JsonFormat( shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss") public Date eventDate;}@Testpublic void whenSerializingUsingJsonFormat_thenCorrect() throws JsonProcessingException, ParseException { SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); df.setTimeZone(TimeZone.getTimeZone("UTC")); String toParse = "20-12-2014 02:30:00"; Date date = df.parse(toParse); EventWithFormat event = new EventWithFormat("party", date); String result = new ObjectMapper().writeValueAsString(event); assertThat(result, containsString(toParse));}
2.20、@JsonUnwrapped
-
去掉属性外壳,有点类似java8 map flat 操作
-
public class UnwrappedUser { public int id; @JsonUnwrapped public Name name; public static class Name { public String firstName; public String lastName; }}@Testpublic void whenSerializingUsingJsonUnwrapped_thenCorrect() throws JsonProcessingException, ParseException { UnwrappedUser.Name name = new UnwrappedUser.Name("John", "Doe"); UnwrappedUser user = new UnwrappedUser(1, name); String result = new ObjectMapper().writeValueAsString(user); assertThat(result, containsString("John")); assertThat(result, not(containsString("name")));} -
输出
-
{ "id":1, "firstName":"John", "lastName":"Doe"}
-
2.21、@JsonView
-
json视图,定义一些标签,每次只序列化特定视图
-
public class Views { public static class Public {} public static class Internal extends Public {}}public class Item { @JsonView(Views.Public.class) public int id; @JsonView(Views.Public.class) public String itemName; @JsonView(Views.Internal.class) public String ownerName;}@Testpublic void whenSerializingUsingJsonView_thenCorrect() throws JsonProcessingException { Item item = new Item(2, "book", "John"); String result = new ObjectMapper() .writerWithView(Views.Public.class) .writeValueAsString(item); assertThat(result, containsString("book")); assertThat(result, containsString("2")); assertThat(result, not(containsString("John")));}
2.22、@JsonManagedReference
-
@JsonBackReference
-
解决循环引用问题
-
public class ItemWithRef { public int id; public String itemName; @JsonManagedReference public UserWithRef owner; } public class UserWithRef { public int id; public String name; @JsonBackReference public List<ItemWithRef> userItems; } @Test public void whenSerializingUsingJacksonReferenceAnnotation_thenCorrect() throws JsonProcessingException { UserWithRef user = new UserWithRef(1, "John"); ItemWithRef item = new ItemWithRef(2, "book", user); user.addItem(item); String result = new ObjectMapper().writeValueAsString(item); assertThat(result, containsString("book")); assertThat(result, containsString("John")); assertThat(result, not(containsString("userItems"))); }
2.23、@JsonIdentityInfo
-
也是解决循环依赖问题,它会标记循环起点
-
@JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class ItemWithIdentity { public int id; public String itemName; public UserWithIdentity owner; } @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class UserWithIdentity { public int id; public String name; public List<ItemWithIdentity> userItems; } @Test public void whenSerializingUsingJsonIdentityInfo_thenCorrect() throws JsonProcessingException { UserWithIdentity user = new UserWithIdentity(1, "John"); ItemWithIdentity item = new ItemWithIdentity(2, "book", user); user.addItem(item); String result = new ObjectMapper().writeValueAsString(item); assertThat(result, containsString("book")); assertThat(result, containsString("John")); assertThat(result, containsString("userItems")); } -
输出
-
{ "id": 2, "itemName": "book", "owner": { "id": 1, "name": "John", "userItems": [ 2 ] } }
-
2.24、@JsonFilter
-
json过滤器,过滤某个字段
-
@JsonFilter("myFilter") public class BeanWithFilter { public int id; public String name; } @Test public void whenSerializingUsingJsonFilter_thenCorrect() throws JsonProcessingException { BeanWithFilter bean = new BeanWithFilter(1, "My bean"); FilterProvider filters = new SimpleFilterProvider().addFilter( "myFilter", SimpleBeanPropertyFilter.filterOutAllExcept("name")); String result = new ObjectMapper() .writer(filters) .writeValueAsString(bean); assertThat(result, containsString("My bean")); assertThat(result, not(containsString("id"))); }
引用
例子来自于: [Jackson Annotation Examples](
本文详细介绍了Jackson库中各种注解的功能与应用场景,包括解决JSON字段与Java Bean字段不匹配的问题,以及如何处理多态、循环引用等复杂情况。
396

被折叠的 条评论
为什么被折叠?



