杰克逊解串器委托给一个适用的解串器

Jaagup库慕尔:

我有我用它来查询一些数据的外部服务。该数据将在两种格式(第一个是这样的“传统”,但支持的需要)之一:

{
    "foo": "John Smith"
}

要么

{
    "foo": {
        "name": "John Smith",
        "bar": "baz"
    }
}

这是我想要映射到以下POJO:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Outer {

    private Foo foo;

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class Foo {

        String name;
        String bar;

    }

}

数据在第二格式(foo是一个对象)应该被反序列化就像任何其他的POJO,但在第一格式给出的数据(foo是字符串),把它变成一个实例Foo,我想打电话new Foo(<foo>, null)要做到这一点,我创建了一个自定义解串器(@JsonComponent意味着该解串器将一个有点-全球注册ObjectMapper弹簧通过杰克逊Module接口):

@JsonComponent
public class FooDeserializer extends JsonDeserializer<Outer.Foo> {

    @Override
    public Outer.Foo deserialize(JsonParser parser, DeserializationContext context)
            throws IOException {
        JsonNode node = parser.getCodec().readTree(parser);
        if (node.isTextual()) {
            return new Foo(node.asText(), null);
        }
        return <delegate to next applicable deserializer>;
    }

}

我有麻烦搞清楚如何做到“授人以一个适用解串器”的一部分,因为每一个解决方案我已经尝试(例如parser.getCodec().treeToValue(node, Outer.Foo.class))再次使用相同的自定义解串器,引起无限递归结束。这甚至可能吗?

Smbchde:

感谢schummar答案:我怎么叫从杰克逊定制的解串器的默认解串器按照上面的答案,
1 @JsonComponent注释应该从自定义序列中删除,因为我们需要建立基于默认的序列自定义序列化,这是不被支持@JsonComponent
2.注册一个SimpleModuleObjectMapper一个BeanDeserializerModifier和修改串行的,我们与默认的序列构建自定义序列。
3.在serialize自定义序列化的方法,处理的特殊情况,并委托系列化正常情况下,默认的序列。

下面的代码演示了如何实现上述各点。

大类

import java.io.IOException;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
import com.fasterxml.jackson.databind.module.SimpleModule;

public class DelegateDeserializer {
    public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {

        ObjectMapper mapper = new ObjectMapper();

        SimpleModule simpleModule = new SimpleModule();

        simpleModule.setDeserializerModifier(new BeanDeserializerModifier() {
            @Override
            public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc,
                    JsonDeserializer<?> deserializer) {
                if (Outer.Foo.class.isAssignableFrom(beanDesc.getBeanClass())) {
                    return new FooDeserializer(deserializer, beanDesc.getBeanClass());
                }
                return deserializer;
            }
        });

        mapper.registerModule(simpleModule);

        Outer outer1 = mapper.readValue(getType1Json(), Outer.class);
        Outer outer2 = mapper.readValue(getType2Json(), Outer.class);
        System.out.println("deserialize json with object structure:");
        System.out.println(outer1.getFoo().getName());
        System.out.println(outer1.getFoo().getBar());
        System.out.println("deserialize json with string field only:");
        System.out.println(outer2.getFoo().getName());
        System.out.println(outer2.getFoo().getBar());
    }

    private static String getType1Json() {

        return "  {                                                                        "
                + "  \"foo\": {                                                            "
                + "     \"name\": \"John Smith\",                                          "
                + "    \"bar\": \"baz\"                                                    "
                + "   }                                                                    "
                + "}                                                                       ";

    }

    private static String getType2Json() {

        return "  {                                                                        "
                + "  \"foo\": \"John Smith\"                                               "
                + "}                                                                       ";

    }
}

FooDeserializer类

import java.io.IOException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.ResolvableDeserializer;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;

import jackson.Outer.Foo;

public class FooDeserializer extends StdDeserializer<Outer.Foo> implements ResolvableDeserializer {

    private static final long serialVersionUID = 1L;
    private final JsonDeserializer<?> defaultDeserializer;

    public FooDeserializer(JsonDeserializer<?> defaultDeserializer, Class<?> clazz) {
        super(clazz);
        this.defaultDeserializer = defaultDeserializer;
    }

    @Override
    public Outer.Foo deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        if (parser.getCurrentToken() == JsonToken.VALUE_STRING) {
            JsonNode node = parser.getCodec().readTree(parser);
            if (node.isTextual()) {
                return new Foo(node.asText(), null);
            }
        }

        return (Foo) defaultDeserializer.deserialize(parser, context);
    }

    @Override
    public void resolve(DeserializationContext ctxt) throws JsonMappingException {
        ((ResolvableDeserializer) defaultDeserializer).resolve(ctxt);
    }

}

外部类

 public class Outer {
    private Foo foo;

    public Foo getFoo() {
        return foo;
    }

    public void setFoo(Foo foo) {
        this.foo = foo;
    }

    public static class Foo {
        private String bar;
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getBar() {
            return bar;
        }

        public void setBar(String bar) {
            this.bar = bar;
        }

        public Foo() {
        }

        public Foo(String name, String bar) {
            this.name = name;
            this.bar = bar;
        }
    }

}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

杰克逊连锁定制解串器

如何提供与杰克逊和Spring启动自定义解串器

杰克逊:如何使@JsonBackReference和自定义解串器同时工作?

杰克逊解串器没有默认的(无ARG)构造

杰克逊中用于枚举的自定义xml解串器

我如何让杰克逊找到我的密钥解串器?

杰克逊自定义解串器未调用

杰克逊在不同情况下使用不同的解串器

是否有可能在类级别不同的数据类型配置杰克逊定制的解串器?

杰克逊反序列化不是在自定义解串器调用反序列化

映射一个JSON字符串与杰克逊对象将抛出MismatchedInputException

有没有在杰克逊反序列化单值值对象(不定制解串器)的通用方式

有什么方法可以为嵌套在杰克逊的Optional内的类型指定自定义解串器吗?

杰克逊:如果有多个串行器,则使用哪一个?

杰克逊无法使用一个参数构造器构造实例

如何分析领域可能是一个字符串,并且可以与杰克逊的数组

在杰克逊中将一个字段从字符串更改为json对象

不可变包装器作为杰克逊中的字符串

杰克逊对象映射器未从Java对象创建正确的Json字符串

杰克逊库1.x数组,如果一个元素有时只是一个字符串

杰克逊JSON映射器

杰克逊映射器错误

杰克逊ObjectMapper writeValueAsBytes方法向已经包含反斜杠的字符串中添加另一个反斜杠

有关逗号杰克逊CSV解析器扼流圈分隔值的文件,如果“”是一个域,即使使用引号“

Json解串器

我可以在GSON的另一个自定义解串器中应用自定义解串器吗

杰克逊流API与杰克逊映射器

地图字符串使用杰克逊继承对象

杰克逊解析字符串字段作为JSON