我试图从包含地图的非标准表示形式的csv字符串中反序列化一个数组(该数组通过Lombok使用生成器模式,带有@Jacksonized
)。
我的主题:
@JsonPropertyOrder({
"strField",
"mapField",
})
@Getter
@Jacksonized
@Builder(toBuilder = true)
@EqualsAndHashCode
@ToString
public class MyObject {
private final String strField;
@Builder.Default
private final Map<String, Float> mapField = new HashMap<>();
}
具有非标准映射域表示的csv示例:
strField,mapField
abc,"key1=2.0;key2=3.0"
我正在使用混合来尝试在不重写整个对象的情况下实现这一点:
@JsonPropertyOrder({
"strField",
"mapField",
})
public abstract class MyObjectDeserializerMixin {
@JsonDeserialize(using = StringToMapDeserializer.class)
private Map<String, Float> mapField;
}
...正如您在上面看到的,它指向一个自定义反序列化器:
public class StringToMapDeserializer extends JsonDeserializer<Map<String, Float>> {
@Override
public Map<String, Float> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
String csvFormattedMap = jsonParser.getText().trim();
return Arrays.stream(csvFormattedMap.split(";"))
.map(keyValue -> keyValue.split("="))
.collect(Collectors.toMap(keyValue -> keyValue[0], keyValue -> Float.parseFloat(keyValue[1])));
}
}
总而言之,我正在配置和使用我的CsvMapper,如下所示:
CsvMapper csvMapper = new CsvMapper();
csvMapper.addMixIn(MyObject.class, MyObjectDeserializerMixin.class);
CsvSchema csvSchema = csvMapper
.schemaFor(MyObject.class)
.withHeader();
ObjectReader csvReader = csvMapper.readerFor(MyObject.class).with(csvSchema);
List<MyObject> myObjects = csvReader.<MyObject>readValues(theCsvString).readAll();
但是,我得到以下例外:
通用域名格式。fasterxml。杰克逊。数据绑定。exc.MismatchedInputException:无法构造java的实例。util。LinkedHashMap(尽管至少存在一个创建者):在[源:(StringReader);行:2,列:53](通过引用链:myPackage.MyObject$MyObjectBuilder[“mapField”])处,没有从字符串值('key1=2.0;key2=3.0)反序列化的字符串参数构造函数/工厂方法
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1432)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1062)
at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:371)
at com.fasterxml.jackson.databind.deser.ValueInstantiator.createFromString(ValueInstantiator.java:258)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:357)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:29)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeSetAndReturn(MethodProperty.java:158)
at com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer.vanillaDeserialize(BuilderBasedDeserializer.java:269)
at com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer.deserialize(BuilderBasedDeserializer.java:193)
at com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1719)
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1261)
...
堆栈跟踪似乎试图使用一个BuilderBasedDeserializer,它试图使用映射反序列化器。java,因此它似乎不知道我的自定义反序列化程序。我使用了一个非常类似的工作流和一个自定义序列化程序来编写相同的csv,所以我不明白为什么这不起作用。排除故障的下一步是什么?
当使用生成器反序列化时,Jackson只考虑生成器类上的注释,而不考虑要反序列化的实际类上的注释。龙目的Jacksonized帮助您自动将所有相关注释复制到生成器类及其setter方法。
然而,Lombok只能在类上静态显示注释的情况下才能做到这一点。来自mixin的任何动态注释都无法复制,因为龙目岛不知道它们。您可以将@jsondeseialize
放在实际类的映射字段中,这样龙目就能将其复制到生成器中。但这显然与混合的目的背道而驰。
幸运的是,还有更好的方法。您还可以将mixin添加到builder类中,如下所示:
csvMapper.addMixIn(MyObjectBuilder.class, MyObjectDeserializerMixin.class);
严格来说,您不再需要MyObject上的mixin。但是,如果您也进行了序列化,并且mixin中有与序列化相关的注释,那么您应该将mixin添加到这两者中。
然而,在您的情况下,这还不够,因为您使用的是构建器。默认值。通过该注释,Lombok在生成器中创建了一个名为mapField$value的字段。Jackson不会将mixin中的字段(及其注释)与该字段匹配,因为它们的名称不同。您可以通过在mixin中定义和注释setter方法来解决这个问题:
public abstract class MyObjectDeserializerMixin {
@JsonDeserialize(using = StringToMapDeserializer.class)
public abstract void mapField(Map<String, Float> mapField);
}
您可以在此处使用构建器的实际返回类型,但val
也足够了。由于@JsonDeserializ
仅用于反序列化目的,您可以安全地从混合类中删除mapField
及其注释。
用龙目1.18.20和杰克逊2.12.2测试。
我正在尝试反序列化以下JSON 在以下自定义反序列化程序的帮助下 进入以下对象结构 我得到以下错误 通用域名格式。fasterxml。杰克逊。数据绑定。exc.MismatchedInputException:无法构造OrderId的实例(尽管至少存在一个创建者):没有从字符串值反序列化的字符串参数构造函数/工厂方法({“type”:“TAKEAWAY”,“data”:{“OrderId”:“AW
问题内容: 使用包中的类时遇到了json解析问题,而我得到的错误是: 发生此问题的Web应用程序是使用AngularJS前端的Spring MVC应用程序,但我可以使用更小的所有Java程序来复制该问题。这是我的豆子: Shipment.java Activity.java ActivityLocation.java 地址.java 这是我可以正确映射json的代码: 调整var中的数据时,遇到了
我使用RestTemplate。exchange在我的Spring Boot应用程序中获得以下响应: 广告商。java: 广告商java: 但我有以下例外: 我不明白为什么id“1057343”不能反序列化。 你能帮忙吗?提前谢谢
我正在尝试使用RestTemplate(Spring Boot)读取来自rest服务的响应: 但当响应中存在错误数组时: 我不明白为什么没有构造器/工厂方法从字符串值反序列化。 谢谢
我是Spring DataJPA+REST项目的新手,我正在尝试使用OneToOne单向关系执行从reference EmployerType添加新的或编辑雇主。当我试图添加或编辑数据时,我会得到以下错误: 下面是关于这些课程的信息。 Rest控制器
当我在Spring Data REST应用程序中使用Lombok来定义复杂类型时,例如: 使用Spring Data REST控制器,例如: 我遇到了一个可怕的错误: 来自Spring Data REST使用Jackson和Book POST,例如: 当Jackson试图解析本地URI时,会发生反序列化错误,该URI应解析为单个唯一的人。如果我删除我的RepositoryRestControlle