skip to Main Content

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


  1. Chosen as BEST ANSWER

    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,

    ObjectMapper mapper = new ObjectMapper();
    DeserializationConfig deserializationConfig = mapper.getDeserializationConfig();
    DeserializationConfig modifiedConfig = deserializationConfig.withAttribute("mappingData", map);
    mapper.setConfig(modifiedConfig);
    

    Then access the passed information through the deserializer in this way,

    public com.sysco.site_product.models.pisv2.Split deserialize(JsonParser jp, DeserializationContext context) throws IOException {
          Map<String, Object> inputJSONMap = (Map<String, Object>) context.getAttribute("mappingData");
    
    ......
    
    }
    

    Open for feedbacks!


  2. 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 for Product Class and maintaion all the field in your self, so you could no effect by the parse order.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search