Reputation: 507
I'm doing some changes in a microservice which has an object like the following:
@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 {
}
}
I'm getting the information that I'm going to use from a Json. That Json has a key called rate
and I want to use that rate in two different variables, an int rate and a Float ratePPR. The problem here is that I know I can't have two variables from the same Json in the same object, but I'm obligated to do it because I can't touch the variable rate
, so I have created the ratePPR
variable to use when I need it.
When I'm testing I get the following error:
Conflicting getter definitions for property "rate": UsageRate#getRate(0 params) vs UsageRate#getRatePPR(0 params) at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:295) at com.fasterxml.jackson.databind.SerializerProvider.reportMappingProblem(SerializerProvider.java:1309) at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider
What can I do to create the new variable ratePPR
with the value from rate JSon value.
Another thing important to say is the attribute in the DB can be a fractional, so, I need to save in the first place the value in ratePPR
and after of that I need to save the integer value in rate
variable.
Upvotes: 1
Views: 1495
Reputation: 4009
You're almost there because I noticed that you have added @JsonDeserialize
to your UsageRate
class. So the key is how to implement your custom deserializer. Here comes an example:
Step 1: Create your custom deserializer and map the field rate to both variables(rate
and ratePPR
).
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);
}
}
Step 2: Annotate UsageRate
with @JsonDeserialize(using = UsageRateDeserializer.class)
@ToString
@Getter
@Setter
@AllArgsConstructor
@JsonDeserialize(using = UsageRateDeserializer.class)
class UsageRate implements Serializable {
private int rate;
private Float ratePPR;
}
Step 3: Let Jackson
do the rest for you
String jsonStr = "{\"rate\": 50}";
ObjectMapper objectMapper = new ObjectMapper();
UsageRate usageRate = objectMapper.readValue(jsonStr, UsageRate.class);
System.out.println(usageRate.toString());
Console output:
UsageRate{rate=50, ratePPR=50.0}
Upvotes: 0
Reputation: 4547
The issue is due to the fact that your class rate
and ratePPR
fields match the same json rate property either in the deserialization process or serialization process, so as precondition you have to change the name of one of them. One way to solve the problem as from the user Lino's comment below your question is define a JsonCreator
annotated constructor with a float parameter annotated with the @JsonProperty("rate")
and inside define the two fields:
@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;
}
The JsonIgnore
annotation excludes the rateIntegerPart
from the serialization :
//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}
Upvotes: 1