0

I have a JSON as below. The goal is to get the corresponding "ip","PRODUCTTYPE" and "ID" values.

{
    "customerId": "dummy1",
    "nameIdmap": {
        "10.2.1.0": "{PRODUCTTYPE=null, ID=123}",
        "10.2.1.3": "{PRODUCTTYPE=null, ID=456}",
        "10.2.1.4": "{PRODUCTTYPE=null, ID=789}",
        "10.2.1.5": "{PRODUCTTYPE=null, ID=193}"
    }
}

I am using the ObjectMapper API to parse and fetch the values.

ObjectMapper om = new ObjectMapper();
JsonNode node = om.readTree(stringToBeParsed);
String customerID = node.get("customerId").asText();
System.out.println("The Customer ID is ::: "+customerID);
JsonNode nameIdmap = node.get("nameIdmap");
StreamSupport.stream(nameIdmap.spliterator(), false).forEach(
        kv -> {
          System.out.println(kv.asText().split(",")[0] +" , 
          "+kv.asText().split(",")[1]);
});

But the issue is I, am unable to get the key which is the ip-address in this case. Tried different ways to achieve but could not get what i want.

I checked if the nameIdmap is an array nameIdmap.isArray() but it is false.

I also tried below but could not get the ip i.e the key

JsonNode nameIdmap = node.get("nameIdmap"); 
StreamSupport.stream(nameIdmap.spliterator(), false).collect(Collectors.toList())
  .forEach(item -> {
            System.out.println(item.asText());
   });;
4
  • Why don't you just create an annotated POJO to parse the JSON into? Typically the code you're showing would apply to some custom de-serializer logic. Commented Aug 13, 2018 at 14:17
  • In my case both "ip" and "{PRODUCTTYPE=null, ID=123}" needs to be parsed.Editing the json for better understanding. Please take a look. Commented Aug 13, 2018 at 14:22
  • I am not sure how this can be achieved by mapping to a POJO. Commented Aug 13, 2018 at 14:24
  • is your json correct? because right now it is like this "{PRODUCTTYPE=null, ID=123}". shouldn't it be {"PRODUCTTYPE"=null, "ID"=123} ? that means {PRODUCTTYPE=null, ID=123} is a single string instead of an object with two fields .recheck your json if it is correct? Commented Aug 13, 2018 at 14:26

3 Answers 3

3

You can try Custom Deserializer as below

1. Create Item class This is a POJO which stands for an ID and a map of String and IPItem

public class SOItem {
    @Override
    public String toString() {
        return "SOItem [id=" + id + ", map=" + map + "]";
    }
    String id;
    Map<String, SOIPItem> map = new HashMap();

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public Map<String, SOIPItem> getMap() {
        return map;
    }
    public void setMap(Map<String, SOIPItem> map) {
        this.map = map;
    }
}

2. Create IPItem class This is a POJO for an ID and ProductType

public class SOIPItem {
    private String type;
    private String id;

    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "SOIPItem [type=" + type + ", id=" + id + "]";
    }
    public SOIPItem(String type, String id) {
        super();
        this.type = type;
        this.id = id;
    }
}

3. Create a Custom Deserializer

import java.io.IOException;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;

public class SOCustDeser extends StdDeserializer<SOItem> {

    public SOCustDeser() {
        this(null);
    }
    public SOCustDeser(Class<?> vc) {
        super(vc);
    }

    /**
     * 
     */
    private static final long serialVersionUID = -394222274225082713L;

    @Override
    public SOItem deserialize(JsonParser parser, DeserializationContext arg1)
            throws IOException, JsonProcessingException {
        SOItem soItem = new SOItem();

        ObjectCodec codec = parser.getCodec();
        JsonNode node = codec.readTree(parser);

        soItem.setId(node.get("customerId").asText());

        JsonNode idmap = node.get("nameIdmap");
        Iterator<String> fieldNames = idmap.fieldNames();
        while(fieldNames.hasNext()) {
          String ip = fieldNames.next();
          String textValue = idmap.get(ip).asText();

          Pattern p = Pattern.compile("(.*?)=(.*?),(.*?)(\\d+)");
          Matcher m = p.matcher(textValue);
          if (m.find()) {
              soItem.map.put(ip, new SOIPItem(m.group(2), m.group(4)));
          }
        }

        return soItem;
    }
}

4. Test class

import java.io.File;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;

public class MicsTest {
    public static void main(String[] args) throws Exception {
        ObjectMapper om = new ObjectMapper();
        SimpleModule sm = new SimpleModule();
        sm.addDeserializer(SOItem.class, new SOCustDeser());
        om.registerModule(sm);

        SOItem item = om.readValue(new File("c:\\temp\\test.json"), SOItem.class);

        System.out.println(item);
    }
}

5. Output SOItem [id=dummy1, map={10.2.1.0=SOIPItem [type=null, id=123], 10.2.1.3=SOIPItem [type=null, id=456], 10.2.1.5=SOIPItem [type=null, id=193], 10.2.1.4=SOIPItem [type=null, id=789]}]

Sign up to request clarification or add additional context in comments.

Comments

2

You can get the field names by nameIdmap.getFieldNames as an iterator. You can then iterate over like that:

...
Iterator<String> fieldNames = idmap.getFieldNames();
while(fieldNames.hasNext()) {
  String ip = fieldNames.next();
  String textValue = idmap.get(ip).getTextValue()
  System.out.println(ip + ":" + textValue);
}

If the nested information is also JSON you can then access it further via idmap.get(ip).get("ID"); if not then you still have the option to find it by regex like that:

Pattern p = Pattern.compile("ID=(\\d+)");
Matcher m = p.matcher(textValue);
if(m.find()) {
  System.out.println(ip + ":" + m.group(1));
}

3 Comments

Thanks for spending your effort. Even though your answer works like a charm , answer by pvpkiran suits my case. But, your answer was very helpful.
Your welcome. I agree that POJO mapping fits best in this scenario. Nevertheless I would recommend to use a regular expression to extract the 'ID' instead of the split logic as it is a lot more robust (if it's not possible to get this also properly json-formatted). Especially when you're not the owner of the system where the data coming from. Imagine someone would reorder attributes or insert a new one in between (I'm talking only of the '{PRODUCTTYPE=null, ID=123}' part). String-Split logic is error-prone in these cases.
I agree with you.
0

Best way to handle these scenarios is to create a matching pojo for your json. This way it gives you flexibility to play around with the data.

Create classes like these

public class Someclass {

    private String customerId;

    Map<String, String> nameIdmap;

    public Map<String, String> getNameIdmap() {
        return nameIdmap;
    }

    public void setNameIdmap(Map<String, String> nameIdmap) {
        this.nameIdmap = nameIdmap;
    }

    public Someclass() {
    }

    public String getCustomerId() {
        return customerId;
    }

    public void setCustomerId(String customerId) {
        this.customerId = customerId;
    }
}

And this code will translate your json to SomeClass class

String json = "<copy paste your json here>";
Someclass someclass = objectMapper.readValue(json, Someclass.class);
String s = someclass.getNameIdmap().get("10.2.1.0");
String[] splits = s.split(" ");
String productType = splits[0].split("=")[1];
String id = splits[1].split("=")[1];
System.out.println(productType + "  " + id);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.