给定以下类层次结构,我希望根据类层次结构中使用的上下文,对Foo进行不同的序列化。
public class Foo {
public String bar;
public String biz;
}
public class FooContainer {
public Foo fooA;
public Foo fooB;
}
我希望序列化FooContainer时biz属性不显示在fooB中。因此,输出将类似于以下内容。
{
"fooA": {"bar": "asdf", "biz": "fdsa"},
"fooB": {"bar": "qwer"}
}
我本打算使用JsonView,但是必须将其应用于类的所有实例的映射器层,并且这取决于上下文。
在Jackson用户的邮件列表中,Tatu提供了最简单的解决方案(在2.0中可用),我现在可能最终会使用它。将奖励授予jlabedo,因为答案是一个如何使用自定义注释扩展Jackson的绝妙示例。
public class FooContainer {
public Foo fooA;
@JsonIgnoreProperties({ "biz" })
public Foo fooB;
}
您可以结合使用自定义序列化程序和使用JsonViews的自定义属性过滤器。这是使用Jackson 2.0的一些代码
定义一个自定义注释:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FilterUsingView {
Class<?>[] value();
}
定义一些视图:
// Define your views here
public static class Views {
public class Public {};
public class Internal extends Public{};
}
然后,您可以像这样编写实体。请注意,您可以定义自己的注释,而不是使用@JsonView
:
public class Foo {
@JsonView(Views.Public.class)
public String bar;
@JsonView(Views.Internal.class)
public String biz;
}
public class FooContainer {
public Foo fooA;
@FilterUsingView(Views.Public.class)
public Foo fooB;
}
然后,这是代码开始的地方:)首先,您的自定义过滤器:
public static class CustomFilter extends SimpleBeanPropertyFilter {
private Class<?>[] _nextViews;
public void setNextViews(Class<?>[] clazz){
_nextViews = clazz;
}
@Override
public void serializeAsField(Object bean, JsonGenerator jgen,
SerializerProvider prov, BeanPropertyWriter writer)
throws Exception {
Class<?>[] propViews = writer.getViews();
if(propViews != null && _nextViews != null){
for(Class<?> propView : propViews){
System.out.println(propView.getName());
for(Class<?> currentView : _nextViews){
if(!propView.isAssignableFrom(currentView)){
// Do the filtering!
return;
}
}
}
}
// The property is not filtered
writer.serializeAsField(bean, jgen, prov);
}
}
然后AnnotationIntrospector
,将执行以下两项操作的自定义:
@FilterUsingView
注释,则启用您的CustomSerializer 。这是代码
public class CustomAnnotationIntrospector extends AnnotationIntrospector {
@Override
public Version version() {
return DatabindVersion.instance.version();
}
@Override
public Object findFilterId(AnnotatedClass ac) {
// CustomFilter is used for EVERY Bean, unless another filter is defined
Object id = super.findFilterId(ac);
if (id == null) {
id = "CustomFilter";
}
return id;
}
@Override
public Object findSerializer(Annotated am) {
FilterUsingView annotation = am.getAnnotation(FilterUsingView.class);
if(annotation == null){
return null;
}
return new CustomSerializer(annotation.value());
}
}
这是您的自定义序列化程序。它唯一要做的就是将注释的值传递给自定义过滤器,然后让默认的序列化程序完成这项工作。
public class CustomSerializer extends JsonSerializer<Object> {
private Class<?>[] _activeViews;
public CustomSerializer(Class<?>[] view){
_activeViews = view;
}
@Override
public void serialize(Object value, JsonGenerator jgen,
SerializerProvider provider) throws IOException,
JsonProcessingException {
BeanPropertyFilter filter = provider.getConfig().getFilterProvider().findFilter("CustomFilter");
if(filter instanceof CustomFilter){
CustomFilter customFilter = (CustomFilter) filter;
// Tell the filter that we will filter our next property
customFilter.setNextViews(_activeViews);
provider.defaultSerializeValue(value, jgen);
// Property has been filtered and written, do not filter anymore
customFilter.setNextViews(null);
}else{
// You did not define a CustomFilter ? Well this serializer is useless...
provider.defaultSerializeValue(value, jgen);
}
}
}
终于!让我们放在一起:
public class CustomModule extends SimpleModule {
public CustomModule() {
super("custom-module", new Version(0, 1, 0, "", "", ""));
}
@Override
public void setupModule(SetupContext context) {
super.setupModule(context);
AnnotationIntrospector ai = new CustomAnnotationIntrospector();
context.appendAnnotationIntrospector(ai);
}
}
@Test
public void customField() throws Exception {
FooContainer object = new FooContainer();
object.fooA = new Foo();
object.fooA.bar = "asdf";
object.fooA.biz = "fdsa";
object.fooB = new Foo();
object.fooB.bar = "qwer";
object.fooB.biz = "test";
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new CustomModule());
FilterProvider fp = new SimpleFilterProvider().addFilter("CustomFilter", new CustomFilter());
StringWriter writer = new StringWriter();
mapper.writer(fp).writeValue(writer, object);
String expected = "{\"fooA\":{\"bar\":\"asdf\",\"biz\":\"fdsa\"},\"fooB\":{\"bar\":\"qwer\"}}";
Assert.assertEquals(expected, writer.toString());
}
序列化和反序列化的方式不同于 我已经创建了两个序列化程序 和 我用Jackson查看了序列化/反序列化映射 ,但找不到解决方案。
问题内容: 我需要以一种特定的方式配置Jackson,以下将对其进行描述。 带注释的字段仅使用其ID进行序列化: 如果该字段是普通对象,请对其序列化 如果该字段是对象的集合,请序列化一个数组 带注释的字段的属性名称以不同的顺序进行序列化: 如果该字段是普通对象,请在属性名称后添加后缀 如果该字段是对象的集合,请在属性名称后添加后缀 对于注释,我想这样的自定义,最好有一个可选的值来覆盖名字就像做 用
问题内容: 如何将作为地图的属性序列化为地图的值列表?我已经能够使用吸气剂上的注释进行其他简单的转换。但是,我不确定我想做什么。 问题答案: 我们需要类似的东西,在我们的案例中,我们使用了您所评论的自定义项,这很简单: 使用它的代码:
我有一个类,它可以很好地序列化和反序列化: 我还有一个< code>PacketResponse对象,类似于: 对象的序列化工作正常,结果如下: 然而,当我试图将这个JSON反序列化回一个< code>PacketResponse对象时,使用 我得到一个。 似乎它正在尝试反序列化 ,但由于它没有直接执行此操作,杰克逊看不到 注释,而是正在寻找 字段(因为这是构建器方法的名称)。 有人能帮我找出反序
我已经在google上搜索了将近一天这个问题,并尝试了几个修复(包括StackOverflow的4或5个),但都没有成功。我有一个带注释的POJO,用于Jackson 2.10.2 我使用这个POJO为一些外部请求创建XML。一切都很好,但现在我需要重新排序生成的XML中的字段,似乎什么都不起作用。 我首先尝试在班级层面进行设置: 然后,我尝试使用以下命令设置每个字段的顺序: 我还尝试在所有字段上
我得到了以下代码: 我得到了这个: {"时间":{"小时": 20,"分钟": 49,"秒": 42,"纳米": 99000000,"一天": 19,"一天":"星期四","月":"一月","一天": 19,"年": 2017,"月值": 1,"年表":{"id":"ISO","calendarType":"iso8601"}}} 我要实现的是ISO8601中的字符串 2017-01-19T18: