做电影网站要懂代码,商丘简淘网络科技有限公司,html免费网站模板带后台,wordpress变性介绍 Spring中从JSON到JSON的序列化/反序列化已广泛用于基于Spring的现代应用程序中。 它基于杰克逊。 Jackson可以轻松地将任何POJO序列化为JSON#xff0c;反之亦然。 这段代码写得很好。 我从未遇到任何问题。 当涉及到自定义序列化程序时#xff0c;它将变得更加困难。 这… 介绍 Spring中从JSON到JSON的序列化/反序列化已广泛用于基于Spring的现代应用程序中。 它基于杰克逊。 Jackson可以轻松地将任何POJO序列化为JSON反之亦然。 这段代码写得很好。 我从未遇到任何问题。 当涉及到自定义序列化程序时它将变得更加困难。 这篇文章展示了如何在带有自动装配字段的Spring中使用自定义序列化程序。 定义自定义序列化器 通常自定义类的自定义序列化器继承自 com.fasterxml.jackson.databind.ser.std.StdSerializer。 此类定义了一些构造函数但是框架只需要一个无参数的构造函数即可调用超类如下所示 public CustomSerializer() {this(null);
}public CustomSerializer(ClassObjectToSerialize t) {super(t);
} 然后是实际编写JSON必须实现的主要方法 Override
public void serialize(ObjectToSerialize value, JsonGenerator gen, SerializerProvider provider) throws IOException {gen.writeStartObject();...provider.defaultSerializeField(some field, value.getField(), gen);...gen.writeEndObject();
} 创建序列化程序类时必须将其注册为ObjectToSerialize的序列化程序。 这可以通过在类上使用JsonSerialize注释来完成 JsonSerialize(using CustomSerializer.class)
public class ObjectToSerialize { 现在杰克逊将对该类的所有实例使用此自定义序列化程序。 如有必要可以通过子类编写自定义解串器 com.fasterxml.jackson.databind.deser.std.StdDeserializer T 循环引用和JsonIdentityInfo 对于大多数使用Spring和Hibernate的商业应用迟早会出现循环引用的问题。 这是一个简单的例子。 我们有2个课程 public class Building {IdGeneratedValue(parameters)private Long id;private SetApartment apartments;
}public class Apartment {IdGeneratedValue(parameters)private Long id;private Building building;
} 如果我们尝试序列化至少有一个公寓的建筑物则会收到StackOverflowException。 杰克逊有一个解决此问题的方法-JsonIdentityInfo。 如果将注释JsonIdentityInfo添加到此类则 JsonIdentityInfo(generator ObjectIdGenerators.PropertyGenerator.class, property id)
public class ObjectToSerialize { 那么任何ObjectMapper都将通过用其ID替换除第一个对象以外的所有对象的出现而打破循环。 像这样 {id: 1,apartments: [{id: 2,building: 1 - the object is replaced with its ID},{id: 3,building: 1 - the object is replaced with its ID}]
} 这些是Jackson提供的用于自定义序列化和处理循环引用的工具。 JSON结构问题 问题 JsonIdentityInfo适用于简单的应用程序。 但是随着应用程序以默认格式增长它可能会影响JSON的结构。 例如如果某些方法在一个响应中返回建筑物和区域则可能会发生以下情况 {buildings: [{id: 1,apartments: [{id: 2,building: 1 - the object is replaced with its ID},{id: 3,building: 1 - the object is replaced with its ID}]}],districts: [{buildings: [{id: 5,...},1, - the object is replaced with its ID{id: 6,...}]}]
} 从解析器的角度来看这种替换可能非常不可预测。 在数组中它可能会遇到对象和ID。 这可能发生在任何字段和任何对象上。 如果序列化提供程序多次发现该对象则使用JsonIdentityInfo对该类进行注释的任何对象都将替换为其ID。 序列化提供程序找到的具有相同ID的每个第二第三第四等实例都将替换为其ID。 解 这里的解决方案是使用单独的ObjectMapper编写JSON的一部分。 已经看到的ID的列表存储在由ObjectMapper创建的序列化提供程序中。 通过创建单独的ObjectMapper具有可能不同的配置可以重置列表。 对于返回不同对象类型的“复合” JSON结果可以编写自定义序列化程序。 在此自定义序列化程序中“标头”是使用JsonGenerator方法手动编写的当达到JSON中的正确级别时我们将创建一个新的ObjectMapper并编写外观更好的JSON。 {buildings: [ - create a new ObjectMapper{id: 1,apartments: [{id: 2,building: 1 - the object is replaced with its ID},{id: 3,building: 1 - the object is replaced with its ID}]}],districts: [ - create a new ObjectMapper{buildings: [{id: 5,...},{ - the object is written as a JSON Object not an IDid: 1,...},{id: 6,...}]}]
} 要将JSON写入原始生成器我们可以使用 ObjectMapper.writeValueAsString和 JsonGenerator.writeRawValueString。 PS也可以通过以下方式创建新的序列化提供程序 DefaultSerializerProvider.createInstanceSerializationConfigSerializerFactory但它可能更复杂。 自定义序列化器自动装配问题 问题 我们希望能够在自定义序列化程序中使用Autowire。 这是Spring的最佳功能之一 实际上如果使用默认的ObjectMapper它就可以工作。 但是如果我们使用JSON结构问题的解决方案则该解决方案不适用于由我们自己的对象映射器实例化的自定义序列化程序。 解 我们自己的对象映射器必须配置有特殊的HandlerInstantiator // try to use the default configuration as much as possible
ObjectMapper om Jackson2ObjectMapperBuilder.json().build();
// This instantiator will handle autowiring properties into the custom serializers
om.setHandlerInstantiator(
new SpringHandlerInstantiator(this.applicationContext.getAutowireCapableBeanFactory())); 如果自定义对象映射器是在另一个由默认ObjectMapper创建的自定义序列化器中创建的则它可以自动装配ApplicationContext。 翻译自: https://www.javacodegeeks.com/2019/01/spring-custom-serializers-jsonidentityinfo.html