无法构造实例(尽管至少存在一个创建者):没有字符串参数构造函数/工厂方法来从字符串值反序列化

问题描述 投票:0回答:1

我的对象映射器将 Redis 中缓存的字符串反序列化为对象时遇到问题。

我们通过@Cacheable将对象缓存到redis中,然后将值放入

"{\"@class\":\"org.BusinessPartyBasicResponse\",\"OutputParameters\":{\"@class\":\"org.BusinessPartyBasicResponse$OutputParameters\",\"X_PARTY_DATA_TABLE\":{\"@class\":\"org.BusinessPartyBasicResponse$OutputParameters$PartyDataTable\",\"X_PARTY_DATA_TABLE_ITEM\":[\"java.util.ArrayList\",[{\"@class\":\"org.BusinessPartyBasicResponse$OutputParameters$PartyDataTable$PartyDataTableItem\",\"TYPECODE\":\"AC\",\"ENTERPRISEID\":\"C4C089BBDD857CDCE0531A1E970A0733\",\"NAME\":\"TEST_NAME CENTER\",\"DOINGBUSINESSASNAME\":null,\"IDENTIFIER\":\"1234\",\"ION\":null,\"COUNTRYCODE\":\"US\",\"STATUS\":\"A\",\"SUPPLIEDSOURCES\":\" \",\"CONTRACT_STATUS\":null,\"OFAC\":null},null]]},\"X_BP_COUNT\":1,\"X_RETURN_STATUS\":\"S\"}}"

我们目前正在使用扩展 GenericJackson2JsonRedisSerializer 的自定义序列化器

我无法更改任何字段名称

但是,当我尝试将其映射回 BasicPartyBasicResponse 时

 public BusinessPartyBasicResponse findByType(BpType bpType) {
        log.info("Find BPs with type=[{}]", bpType);
        Set<String> allBp = ops.keys("common:businessPartyBasic::*");
        BusinessPartyBasicResponse response = new BusinessPartyBasicResponse();
        String bpJson = null;
        for (String bp : allBp) {
            bpJson = ops.opsForValue().get(bp);
            if (bpJson.contains("\"TYPECODE\":\"" + bpType.name().toUpperCase() + "\"")) {
                log.info("bpJson {}", bpJson);
                BusinessPartyBasicResponse basicResponse = null;
                try {
                    basicResponse = mapper.readValue(bpJson, BusinessPartyBasicResponse.class);
                    response.getOutputParameters().setResultsCount(
                            response.getOutputParameters().getResultsCount()
                                    + basicResponse.getOutputParameters().getResultsCount());
                    response.getPartyDataTableItem().addAll(basicResponse.getPartyDataTableItem());
                } catch (JsonProcessingException e) {
                    log.info("error processing json: {}" ,e);
                    return null;
                }
            }
        }
        return response;
    }

它回来了

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `org.BusinessPartyBasicResponse$OutputParameters$PartyDataTable$PartyDataTableItem` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('java.util.ArrayList')
 ...
    at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
    at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1728)
    at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1353)
    at com.fasterxml.jackson.databind.deser.std.StdDeserializer._deserializeFromString(StdDeserializer.java:311)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1495)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:197)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:187)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromArray(CollectionDeserializer.java:355)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:28)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:314)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:314)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:314)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177)
    at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:323)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4674)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3629)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3597)

如上所述,我无法更改 json 字段名称,但这是对象 我们最初是从单独的服务获取对象,因此我们无法更改 @JsonProperty() 名称,我尝试更改变量名称,以便 getter 和 setter 能够更正确地匹配 json 属性字段名称

@Getter
@Setter
@JsonIgnoreProperties(ignoreUnknown = true)
public class BusinessPartyBasicResponse {

    public static final String RETURN_STATUS = "S";

    @JsonProperty("OutputParameters")
    private OutputParameters outputParameters = new OutputParameters();

    @Getter
    @Setter
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class OutputParameters {

        @JsonProperty("X_PARTY_DATA_TABLE")
        private PartyDataTable partyDataTable = new PartyDataTable();

        @JsonProperty("X_BP_COUNT")
        private Integer resultsCount;

        @JsonProperty("X_RETURN_STATUS")
        private String returnStatus;

        @Getter
        @Setter
        @JsonIgnoreProperties(ignoreUnknown = true)
        public static class PartyDataTable {

            @JsonProperty("X_PARTY_DATA_TABLE_ITEM")
            private List<PartyDataTableItem> partyDataTableItem = new ArrayList<>();

            @Getter
            @Setter
            @JsonIgnoreProperties(ignoreUnknown = true)
            public static class PartyDataTableItem {

                @JsonProperty("TYPECODE")
                private String bpTypeCode;

                @JsonProperty("ENTERPRISEID")
                private String bpGuid;

                @JsonProperty("NAME")
                private String name;

                @JsonDeserialize(using = JsonNilToStringDeserializer.class)
                @JsonProperty("DOINGBUSINESSASNAME")
                private String doingBusinessAsName;

                @JsonDeserialize(using = JsonNilToStringDeserializer.class)
                @JsonProperty("IDENTIFIER")
                private String identifier;

                @JsonDeserialize(using = JsonNilToStringDeserializer.class)
                @JsonProperty("ION")
                private String ion;

                @JsonProperty("COUNTRYCODE")
                private String country;

                @JsonProperty("STATUS")
                private String status;

                @JsonDeserialize(using = JsonNilToStringDeserializer.class)
                @JsonProperty("SUPPLIEDSOURCES")
                private String suppliedSource;

                @JsonDeserialize(using = JsonNilToStringDeserializer.class)
                @JsonProperty("CONTRACT_STATUS")
                private String contractStatus;

                @JsonDeserialize(using = JsonNilToStringDeserializer.class)
                @JsonProperty("OFAC")
                private String restrictionType;

                @JsonIgnore
                public boolean isRestricted() {
                    return this.restrictionType != null;
                }
            }

        }
    }
java spring redis jackson jackson-databind
1个回答
0
投票

问题在于使用对象映射器。 对于使用特定序列化器(genericjackson2redis)的自定义redis序列化器,我相信它是使用通用对象映射器来反序列化。但这是不正确的,所以我自动连接了自定义序列化器并使用提供的反序列化函数并且它起作用了。

© www.soinside.com 2019 - 2024. All rights reserved.