首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用Jackson & Lombok反序列化ImmutableList

用Jackson & Lombok反序列化ImmutableList
EN

Stack Overflow用户
提问于 2020-05-19 20:36:35
回答 2查看 3.2K关注 0票数 2

我试图让下面的示例工作起来:

代码语言:javascript
运行
复制
    @Value
    @JsonDeserialize(builder = SomeClass.Builder.class)
    @Builder(builderClassName = "Builder")
    public static class SomeClass {
        @Wither
        ImmutableList<String> words;

        @JsonPOJOBuilder(withPrefix = "")
        public static class Builder {
        }
    }

    @Test
    @SneakyThrows
    public void serializeTest() {
        ObjectMapper objectMapper = new ObjectMapper();
        SomeClass someClass = SomeClass.builder()
            .words(ImmutableList.of("word1", "word2", "word3"))
            .build();
        String jsonString = objectMapper.writeValueAsString(someClass);
        log.info("serialized: {}", jsonString);
        SomeClass newSomeClass = objectMapper.readValue(jsonString, SomeClass.class);
        log.info("done");
        newSomeClass.words.forEach(w -> log.info("word {}", w));
    }

但是它失败了

代码语言:javascript
运行
复制
Caused by: java.lang.IllegalArgumentException: Cannot find a deserializer for non-concrete Collection type [collection type; class com.google.common.collect.ImmutableList, contains [simple type, class java.lang.String]]
    at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.createCollectionDeserializer(BasicDeserializerFactory.java:1205)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:399)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:349)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)

this answer上,我尝试了这样的方法:

代码语言:javascript
运行
复制
    @Value
    @JsonDeserialize(builder = SomeClass.Builder.class)
    @Builder(builderClassName = "Builder")
    public static class SomeClass {
        @Wither
        @JsonDeserialize(using = ImmutableListDeserializer.class)
        ImmutableList<String> words;

        @JsonPOJOBuilder(withPrefix = "")
        public static class Builder {
        }
    }

    @Test
    @SneakyThrows
    public void serializeTest() {
        ObjectMapper objectMapper = new ObjectMapper();
        SomeClass someClass = SomeClass.builder()
            .words(ImmutableList.of("word1", "word2", "word3"))
            .build();
        String jsonString = objectMapper.writeValueAsString(someClass);
        log.info("serialized: {}", jsonString);
        SomeClass newSomeClass = objectMapper.readValue(jsonString, SomeClass.class);
        log.info("done");
        newSomeClass.words.forEach(w -> log.info("word {}", w));
    }

但以下情况却未能实现:

代码语言:javascript
运行
复制
Caused by: java.lang.IllegalArgumentException: Cannot find a deserializer for non-concrete Collection type [collection type; class com.google.common.collect.ImmutableList, contains [simple type, class java.lang.String]]

由于我正在处理的项目的限制,我无法修改对象映射器。所以我不能简单地:

代码语言:javascript
运行
复制
objectMapper.registerModule(new GuavaModule());

这会奏效的。

还有其他简单的方法可以让简单的ImmutableList反序列化工作吗?

编辑:I在下面得到了一个不同的错误:

代码语言:javascript
运行
复制
    @Value
    @JsonDeserialize(builder = SomeClass.Builder.class)
    @Builder(builderClassName = "Builder")
    public static class SomeClass {
        @Wither
        ImmutableList<String> strings;

        @JsonPOJOBuilder(withPrefix = "")
        public static class Builder {
            @JsonDeserialize(using = ImmutableListDeserializer.class)
            public Builder strings(ImmutableList<String> strings) {
                this.strings = strings;
                return this;
            }
        }
    }

    @Test
    @SneakyThrows
    public void serializeTest() {
        ObjectMapper objectMapper = new ObjectMapper();
        SomeClass someClass = SomeClass.builder()
            .strings(ImmutableList.of("word1", "word2", "word3"))
            .build();
        String jsonString = objectMapper.writeValueAsString(someClass);
        log.info("serialized: {}", jsonString);
        SomeClass newSomeClass = objectMapper.readValue(jsonString, SomeClass.class);
        log.info("done");
        newSomeClass.strings.forEach(w -> log.info("word {}", w));
    }

抛出:

代码语言:javascript
运行
复制
Caused by: java.lang.IllegalArgumentException: Class com.fasterxml.jackson.datatype.guava.deser.ImmutableListDeserializer has no default (no arg) constructor

如果我可以为ImmutableListDeserializer构建一个no arg构造函数,或者类似的东西,那么这可能更容易解决。

EN

Stack Overflow用户

回答已采纳

发布于 2020-05-20 13:30:46

最后必须编写自定义序列化程序。如果你有一个更优雅的答案,请告诉我。以下是一个为可能在这里结束的人提供的工作示例:

代码语言:javascript
运行
复制
    @Value
    @JsonDeserialize(builder = SomeClass.Builder.class)
    @Builder(builderClassName = "Builder")
    public static class SomeClass {
        @Wither
        ImmutableList<String> strings;

        @JsonPOJOBuilder(withPrefix = "")
        public static class Builder {
            @JsonDeserialize(using = CustomDeserializer.class)
            public Builder strings(ImmutableList<String> strings) {
                this.strings = strings;
                return this;
            }
        }
    }

    public static class CustomDeserializer extends StdDeserializer<ImmutableList<String>> {
        public CustomDeserializer() {
            super(ImmutableList.class);
        }

        @Override
        public ImmutableList<String> deserialize(JsonParser parser, DeserializationContext deserializer) throws IOException {
            ImmutableList.Builder<String> immutableListBuilder = ImmutableList.builder();
            while (!parser.isClosed()) {
                JsonToken jsonToken = parser.nextToken();
                if (JsonToken.VALUE_STRING.equals(jsonToken)) {
                    final String fieldValue = parser.getValueAsString();
                    immutableListBuilder.add(fieldValue);
                } else if (JsonToken.END_ARRAY.equals(jsonToken)) {
                    break;
                }
            }
            return immutableListBuilder.build();
        }
    }

    @Test
    @SneakyThrows
    public void serializeTest() {
        ObjectMapper objectMapper = new ObjectMapper();
        SomeClass someClass = SomeClass.builder()
            .strings(ImmutableList.of("word1", "word2", "word3"))
            .build();
        String jsonString = objectMapper.writeValueAsString(someClass);
        log.info("serialized: {}", jsonString);
        SomeClass newSomeClass = objectMapper.readValue(jsonString, SomeClass.class);
        log.info("done");
        newSomeClass.strings.forEach(w -> log.info("word {}", w));
    }

我发现了一篇很好的关于这个的文章:http://tutorials.jenkov.com/java-json/jackson-objectmapper.html

票数 0
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61900327

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档