【问题标题】:Mapping the same Json key in different variables in the same object在同一对象的不同变量中映射相同的 Json 键
【发布时间】:2022-01-20 15:22:50
【问题描述】:

我正在对具有如下对象的微服务进行一些更改:

@ToString
@Getter
@Setter
@Builder
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonDeserialize(builder = UsageRate.UsageRateBuilder.class)
public class UsageRate implements Serializable {


private int rate;

@JsonProperty("rate")
private Float ratePPR;

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

}

我正在从 Json 获取我将要使用的信息。该 Json 有一个名为 rate 的键,我想在两个不同的变量中使用该速率,一个 int rate 和一个 Float ratePPR。这里的问题是我知道我不能在同一个对象中拥有来自同一个 Json 的两个变量,但我有义务这样做,因为我无法触及变量 rate,所以我创建了 @987654324 @ 变量在我需要时使用。

我在测试时收到以下错误:

属性“rate”的 getter 定义冲突: UsageRate#getRate(0 参数) 与 UsageRate#getRatePPR(0 参数) 在 com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:295) 在 com.fasterxml.jackson.databind.SerializerProvider.reportMappingProblem(SerializerProvider.java:1309) 在 com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider

我可以做些什么来创建新变量ratePPR 使用来自速率 JSON 值的值。 另一件重要的事情是数据库中的属性可以是小数,因此,我需要首先将值保存在ratePPR 中,然后我需要将整数值保存在rate 变量中。

【问题讨论】:

  • 使用自定义@JsonCreator 怎么样?这样您就可以在构造函数中正确地将rate 字段映射到ratePPR
  • 你好@Lino 我正在尝试使用@JsonCreator 问题是我正在使用@Builder@JsonPOJOBuilder 来反序列化Json,现在当我获取信息时出现错误来自 Json。

标签: java json jackson lombok


【解决方案1】:

问题是由于您的类 rateratePPR 字段在反序列化过程或序列化过程中匹配相同的 json rate 属性,因此您必须更改前提条件其中之一的名字。根据用户 Lino 在您的问题下方的评论,解决该问题的一种方法是定义一个带有 @JsonProperty("rate") 注释的浮点参数的 JsonCreator 带注释的构造函数,并在内部定义两个字段:

@ToString
@Getter
@Setter
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UsageRate implements Serializable {

    @JsonCreator
    public UsageRate(@JsonProperty("rate") float rate) {
        this.rateIntegerPart = (int) rate;
        this.ratePPR = rate;
    }

    @JsonIgnore
    private int rateIntegerPart;

    @JsonProperty("rate")
    private Float ratePPR;
}

JsonIgnore 注释从序列化中排除了rateIntegerPart

//json = {"rate":10.0}
UsageRate rate = mapper.readValue(json, UsageRate.class);
System.out.println(rate); //it prints UsageRate(rateIntegerPart=10, ratePPR=10.0)
System.out.println(mapper.writeValueAsString(rate)); // it prints {"rate":10.0}

【讨论】:

    【解决方案2】:

    您快到了,因为我注意到您已将 @JsonDeserialize 添加到您的 UsageRate 课程中。所以关键是如何实现你的自定义反序列化器。举个例子:

    第 1 步:创建自定义反序列化程序并将字段 rate 映射到两个变量(rateratePPR)。

    class UsageRateDeserializer extends StdDeserializer<UsageRate> {
        public UsageRateDeserializer() {
            this(null);
        }
    
        protected UsageRateDeserializer(Class<?> vc) {
            super(vc);
        }
    
        @Override
        public UsageRate deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
            JsonNode jsonNode = jsonParser.getCodec().readTree(jsonParser);
            int rate = jsonNode.get("rate").asInt();
            Float ratePPR = jsonNode.get("rate").floatValue();
    
            return new UsageRate(rate, ratePPR);
        }
    }
    

    第 2 步:用 @JsonDeserialize(using = UsageRateDeserializer.class) 注释 UsageRate

    @ToString
    @Getter
    @Setter
    @AllArgsConstructor
    @JsonDeserialize(using = UsageRateDeserializer.class)
    class UsageRate implements Serializable {
        private int rate;
        private Float ratePPR;
    }
    

    第 3 步:让Jackson 为您完成剩下的工作

    String jsonStr = "{\"rate\": 50}";
    
    ObjectMapper objectMapper = new ObjectMapper();
    UsageRate usageRate = objectMapper.readValue(jsonStr, UsageRate.class);
    System.out.println(usageRate.toString());
    

    控制台输出:

    UsageRate{rate=50, ratePPR=50.0}

    【讨论】:

      猜你喜欢
      • 2022-01-07
      • 1970-01-01
      • 1970-01-01
      • 2013-01-19
      • 2016-08-05
      • 2018-11-13
      • 1970-01-01
      • 1970-01-01
      • 2015-06-28
      相关资源
      最近更新 更多