我试图让下面的示例工作起来:
@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));
}
但是它失败了
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上,我尝试了这样的方法:
@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));
}
但以下情况却未能实现:
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]]
由于我正在处理的项目的限制,我无法修改对象映射器。所以我不能简单地:
objectMapper.registerModule(new GuavaModule());
这会奏效的。
还有其他简单的方法可以让简单的ImmutableList反序列化工作吗?
编辑:I在下面得到了一个不同的错误:
@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));
}
抛出:
Caused by: java.lang.IllegalArgumentException: Class com.fasterxml.jackson.datatype.guava.deser.ImmutableListDeserializer has no default (no arg) constructor
如果我可以为ImmutableListDeserializer构建一个no arg构造函数,或者类似的东西,那么这可能更容易解决。
发布于 2020-05-20 13:30:46
最后必须编写自定义序列化程序。如果你有一个更优雅的答案,请告诉我。以下是一个为可能在这里结束的人提供的工作示例:
@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
https://stackoverflow.com/questions/61900327
复制相似问题