zyydoosh
zyydoosh

Reputation: 379

How to represent recursive json elements in custom java class

I have the below json which I'm trying to figure out which structure the custom java class can represent. Here is the json:

{
   "04000550":{
      "vr":"SQ",
      "Value":[
         {
            "00100010":{
               "vr":"PN",
               "Value":[
                  {
                     "Alphabetic":"TCGA-17-Z021"
                  }
               ]
            }
         }
      ]
   },
   "04000562":{
      "vr":"DT",
      "Value":[
         "20220103125232.022"
      ]
   },
   "04000563":{
      "vr":"LO",
      "Value":[
         "dcm4chee-arc"
      ]
   },
   "04000564":{
      "vr":"LO"
   },
   "04000565":{
      "vr":"CS",
      "Value":[
         "CORRECT"
      ]
   }
}

I tried Map<String, Tag>, and custom class Tag has vr and Value properties, the problem is that Value can be a list of one String, or a Tag, based on vr attribute (if vr = "SQ", the Value will be of type Tag)

I'm trying to map this json to an appropriate java data structure so that I can use it in primefaces datatable to represent these data in a table for user to edit them, if I represent this json into Map<String, Tag> and Tag has String vr, JsonNode Value, I will not be able to allow edit this Value in primefaces datatable as it needs the Value to be a custom object which has properties to allow setters and getters on it (this is how jsf or primefaces work), so how can I map this json?

This is my primefaces datatable btw.

Upvotes: 0

Views: 102

Answers (1)

stefan-dan
stefan-dan

Reputation: 604

You could use a Custom Deserializer for Jackson and then deserialize your JSON like this:

ObjectMapper mapper = new ObjectMapper();
Map<String, Tag> tagMap = mapper.readValue(json, new TypeReference<>() {});

I tried to make a deserializer. It is dirty but is working.

The POJO classes will look like this:

@JsonDeserialize(using = TagDeserializer.class)
public class Tag {
     public final String type;
     // For other types
     public final List<String> valueList;
     // For `SQ` type
     public final Map<String, NestedTag> tags;

     // AllArgsConstructor, Getters
}

public class NestedTag {
     public final String type;
     public final Map<String, String> valueMap;
     
     // AllArgsConstructor, Getters
}

The dataTable will look like this:

<p:dataTable value="#{tagController.tagMap.entrySet()}" var="entry">
    <p:column headerText="Id">
        <p:outputLabel value="#{entry.key}"/>
    </p:column>

    <p:column headerText="Type">
        <p:inputText value="#{entry.value.type}"/>
    </p:column>

    <p:column headerText="Value">
            <!--   List.toString(), you can replace it with another p:dataTable   -->
        <p:inputText value="#{entry.value.valueList}" rendered="#{entry.value.valueList != null}"/>

        <p:dataTable value="#{entry.value.tags.entrySet()}" var="nestedTag" rendered="#{entry.value.tags != null}">
            <p:column headerText="Id">
                <h:outputLabel value="#{nestedTag.key}"/>
            </p:column>

            <p:column headerText="Type">
                <p:inputText value="#{nestedTag.value.type}"/>
            </p:column>

            <p:column headerText="Value">
                    <!--   Map.toString(), you can replace it with another p:dataTable   -->
                <p:inputText value="#{nestedTag.value.valueMap}"/>
             </p:column>
        </p:dataTable>

    </p:column>

</p:dataTable>

Upvotes: 1

Related Questions