Jackson – 自定义序列化程序,仅覆盖特定字段
我知道如何在Jackson中使用自定义序列化程序(通过扩展JsonSerializer
),但我希望默认的序列化程序适用于所有字段,除了1个字段,我想使用自定义序列化程序覆盖它。
注释不是一个选项,因为我正在序列化生成的类(来自Thrift)。
在编写自定义jackson序列化程序时,如何仅指定要覆盖的某些字段?
更新:
这是我要序列化的类:
class Student { int age; String firstName; String lastName; double average; int numSubjects // .. more such properties ... }
上面的类有很多特性,大多数都使用本机类型。 我想覆盖自定义序列化程序中的一些属性,让Jackson像往常一样处理其余的属性。 例如,我只想将“年龄”字段转换为自定义输出。
我遇到了同样的问题,我用CustomSerializerFactory解决了它。
此方法允许您忽略所有对象或特定类型的某些特定字段。
public class EntityCustomSerializationFactory extends CustomSerializerFactory { //ignored fields private static final Set IGNORED_FIELDS = new HashSet ( Arrays.asList( "class", "value", "some" ) ); public EntityCustomSerializationFactory() { super(); } public EntityCustomSerializationFactory(Config config) { super(config); } @Override protected void processViews(SerializationConfig config, BeanSerializerBuilder builder) { super.processViews(config, builder); //ignore fields only for concrete class //note, that you can avoid or change this check if (builder.getBeanDescription().getBeanClass().equals(Entity.class)){ //get original writer List originalWriters = builder.getProperties(); //create actual writers List writers = new ArrayList (); for (BeanPropertyWriter writer: originalWriters){ String propName = writer.getName(); //if it isn't ignored field, add to actual writers list if (!IGNORED_FIELDS.contains(propName)){ writers.add(writer); } } builder.setProperties(writers); } } }
之后您可以使用以下内容:
objectMapper.setSerializerFactory(new EntityCustomSerializationFactory()); objectMapper.writeValueAsString(new Entity());//response will be without ignored fields
假设您的Target类是
public class Student { int age; String firstName; String lastName; double average; int numSubjects; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public double getAverage() { return average; } public void setAverage(double average) { this.average = average; } public int getNumSubjects() { return numSubjects; } public void setNumSubjects(int numSubjects) { this.numSubjects = numSubjects; } }
您需要编写自定义序列化程序,如下所示
public class MyCustomSerializer extends JsonSerializer { @Override public void serialize(Student value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { if (value != null) { jgen.writeStartObject(); jgen.writeStringField("age", "Age: " + value.getAge()); //Here a custom way to render age field is used jgen.writeStringField("firstName", value.getFirstName()); jgen.writeStringField("lastName", value.getLastName()); jgen.writeNumberField("average", value.getAverage()); jgen.writeNumberField("numSubjects", value.getNumSubjects()); //Write other properties jgen.writeEndObject(); } } }
然后将其添加到ObjectMapper
ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("custom", Version.unknownVersion()); module.addSerializer(Student.class, new MyCustomSerializer()); mapper.registerModule(module);
然后像它一样使用它
Student s = new Student(); s.setAge(2); s.setAverage(3.4); s.setFirstName("first"); s.setLastName("last"); s.setNumSubjects(3); StringWriter sw = new StringWriter(); mapper.writeValue(sw, s); System.out.println(sw.toString());
它会产生ao / p之类的东西
{“age”:“年龄:2”,“firstName”:“first”,“lastName”:“last”,“average”:3.4,“numSubjects”:3}
仅仅因为你不能修改类并不意味着你不能使用注释:只需使用混合注释。 有关如何使用此信息,请参阅此博客条目(或google了解有关“jackson mixin annotations”的更多信息)。
我特意将jackson用于protobuf和thrift生成的类,并且它们工作得非常好。 对于早期的Thrift版本,我不得不禁用“is-setters”的发现,Thrift生成的方法是为了查看是否已经明确设置了特定属性,但是其他方法工作正常。
在@JsonView的帮助下,我们可以决定要序列化的模型类的字段,它们满足最小标准(我们必须定义标准),就像我们可以有一个具有10个属性的核心类,但只有5个属性可以序列化,这对于客户端是必需的只要
只需创建以下类来定义我们的视图:
public class Views { static class Android{}; static class IOS{}; static class Web{}; }
带注释的带注释的模型类:
public class Demo { public Demo() { } @JsonView(Views.IOS.class) private String iosField; @JsonView(Views.Android.class) private String androidField; @JsonView(Views.Web.class) private String webField; // getters/setters ... .. }
现在我们必须通过简单地从spring扩展HttpMessageConverter类来编写自定义json转换器:
public class CustomJacksonConverter implements HttpMessageConverter
现在需要告诉spring使用这个自定义json转换,只需将它放在dispatcher-servlet.xml中即可
这就是你如何决定序列化哪些字段的方法。
感谢名单