I have a JSON object that needs to be deserialized in my use case. Also, I need to generate some fields value combining one or more attributes in the same JSON. So I chose Jackson deserialization and annotated the required fields with relevant deserialization classes like follow
@Getter
@ToString
@JsonIgnoreProperties(ignoreUnknown = true)
public class Product implements Serializable {
@JsonProperty("item_name")
@JsonDeserialize(using = ProductDeserializer.ItemName.class)
private String itemName;
@JsonProperty("item_code")
@JsonDeserialize(using = CommonDeserializer.Trim.class)
private String itemCode;
@JsonProperty("demand_status")
@JsonDeserialize(using = ProductDeserializer.DemandStatus.class)
private boolean isDemandItem;
@JsonProperty("upc")
private long upcCode;
@JsonProperty("store_condition") //multiple attributes uses, ex 'store_code'
@JsonDeserialize(using = ProductDeserializer.StoreConditionDeserializer.class)
private StoreCondition storeCondition;
.....
}
Deserialization class for the storeCondition
variable is as follows,
public static class StoreConditionDeserializer extends JsonDeserializer<StoreCondition> {
@Override
public StoreCondition deserialize(JsonParser jp, DeserializationContext context) throws IOException {
String stock_id = jp.getCodec().readValue(jp, JsonNode.class).asText();
String store_code = jp.getCodec().readValue(jp, JsonNode.class).get("store_code").asText();
/* I need to access several fields from the JSON to generate the object I need,
but some of them are missing here but they exist in the JSON input */
//Also some logic, API calls, etc
return ...;
}
}
This is how my input JSON looks like
{
"_id": 28463836,
"item_name": "john product",
"item_code": "doe code",
"store_code": "T",
"demand_status": "D",
"upc": 874564847,
"store_condition": "F",
"location": "IR",
"W_Code": "X3846"
}
If you take a look at the Pojo class, the last attribute annotated with @JsonProperty("store_condition")
, which is also present in the above JSON. When the deserialization happens, it does not have this complete JSON object within the deserialize
method, it only has the attributes after the store_condition
attribute. But for my use case, I need to access the fields above that, for example, store_code
. But since the store_code
code is located before store_condition
, the store_code
does not available in the deserializer.
This is how I do the deserialization,
ObjectMapper mapper = new ObjectMapper();
Product product = mapper.convertValue(jsonInput, Product.class);
Could someone explain why and how this happens? Also, a way to solve this.
I hope that my question and my requirement is clear. Feel free to drop a comment if you need any clarifications.
The Jackson library I used is group: 'org.apache.beam', name: 'beam-sdks-java-extensions-json-jackson', version: '2.47.0'
2
Answers
I found a workaround solution for this, after we create the
ObjectMapper mapper = new ObjectMapper();
pass the required values to it in the following way,Then access the passed information through the deserializer in this way,
Open for feedbacks!
the JsonParser is fetch data in sequence, when you invoke readValue, it get
F
, and the parser move its cursor to next token, so there is no method to access the store_code field that in the previous. so for your scenario, i think you could add custom deserializer forProduct
Class and maintaion all the field in your self, so you could no effect by the parse order.