简体   繁体   中英

Convert JSON Object as a Flat Obejct with Key value pair

I am getting a JSON object which looks like:

{
    "id": "1",
    "name": "Hw",
    "price": {
        "value": "10"
    },
    {
        "items": [{
            "id": "1"
        }]
    }
}

I want to represent this as flat map, but I want to represent the array of items as a list.

My output should look like:

{
"id": "1",
"name":"Hw",
"price":"10",
"items": ["1"]
}

Can anybody suggest me how I can achieve this? I tried this approach:

How to deserialize JSON into flat, Map-like structure?

Output from the above tried link:

{
"id": "1",
"name":"Hw",
"price.value":"10",
"items[0].id": "1"
}

But it is representing the arrays values as array[0] , array[1] which I don't need. I need this array as a list.

The JSON you've given is not valid. I assume it's:

{
    "id": "1",
    "name": "Hw",
    "price": {
        "value": "10"
    },
    "items": [{
        "id": "1"
    }]
}

There cannot be a generic solution to what you're asking. But for this particular JSON, this will do(using json-simple ):

@SuppressWarnings("unchecked")
public Map<String, String> transform(String inputJSON) throws ParseException {
    Map<String, String> result = new LinkedHashMap<>();
    JSONObject inputJSONObj = (JSONObject) new JSONParser().parse(inputJSON);
    String id = inputJSONObj.getOrDefault("id", "").toString();
    String name = inputJSONObj.getOrDefault("name", "").toString();
    String price = ((JSONObject) inputJSONObj.getOrDefault("price", new JSONObject())).getOrDefault("value", "")
            .toString();
    JSONArray itemsArray = (JSONArray) inputJSONObj.getOrDefault("items", new JSONArray());
    int n = itemsArray.size();
    String[] itemIDs = new String[n];
    for (int i = 0; i < n; i++) {
        JSONObject itemObj = (JSONObject) itemsArray.get(i);
        String itemId = itemObj.getOrDefault("id", "").toString();
        itemIDs[i] = itemId;
    }
    result.put("id", id);
    result.put("name", name);
    result.put("price", price);
    result.put("items", Arrays.toString(itemIDs));
    return result;
}

An approach for you with Gson . This do exactly what you want " represent this as flat map, but I want to represent the array of items as a list"

public class ParseJson1 {
    public static void main (String[] args){
        Type type = new TypeToken<HashMap<String, Object>>() {
        }.getType();
        Gson gson = new Gson();
        String json = "{\n" +
                "           \"id\": \"1\",\n" +
                "           \"name\": \"Hw\", \n" +
                "           \"price\": {\n" +
                "               \"value\": \"10\"\n" +
                "           },\n" +
                "           \"items\": [{\n" +
                "               \"id\": \"1\"\n" +
                "           }]\n" +
                "      }\n";
        HashMap<String, Object> map = gson.fromJson(json, type);
        Object val = null;
        for(String key : map.keySet()){
            val = map.get(key);
            if(val instanceof List){
                for(Object s : (List)val){
                    System.out.println(key + ":" + s);
                }
            } else 
            System.out.println(key + ":" + map.get(key));
        }
    }
}

you have to convert your String in Map collection Map<String, String> which will help you to convert your Map Array to JSON format.

JSONObject jsonObject = new JSONObject();
Map<String, String> mapObject = new HashMap<String, String>();
mapObject.put("id", "1");
mapObject.put("name", "VBage");
mapObject.put("mobile", "654321");

jsonObject.put("myJSON", mapObject);
System.out.println(jsonObject.toString());

First, the JSON does not seems to have a correct format. Do you mean this?

{
    "id": "1",
    "name": "Hw",
    "price": {
        "value": "10"
    },
    "items": [{
        "id": "1"
    }]
}

In addition, since you were attaching the link of ( How to deserialize JSON into flat, Map-like structure? ), I assume you wants to flatten the JSON in the same manner, in which the result should be

{
   id=1,
   name=Hw,
   price.value=10,
   items[0]=1,
}

Also, if you just want the item to return a list of id (ie "items": ["1"]), then it is more logical to get a JSON of

{
    "id": "1",
    "name": "Hw",
    "price": {
        "value": "10"
    },
    "items": [ "1" ] // instead of "items": [{"id": "1"}]

}

The link that you have attached ( How to deserialize JSON into flat, Map-like structure? ) provides a general solution without any customization. It shouldn't know that "id" is the value you want to append on items.

Therefore, my first suggestion is to change the JSON to be "items": [ "1" ]

If for any reasons the JSON cannot be changed, then you will need to do some customization , which will be like this:

import org.codehaus.jackson.*;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ArrayNode;
import org.codehaus.jackson.node.ObjectNode;
import org.codehaus.jackson.node.ValueNode;
import org.junit.Test;

public class Main {
    String json = "{\n" +
            "           \"id\": \"1\",\n" +
            "           \"name\": \"Hw\", \n" +
            "           \"price\": {\n" +
            "               \"value\": \"10\"\n" +
            "           },\n" +
            "           \"items\": [{\n" +
            "               \"id\": \"1\"\n" +
            "           }]\n" +
            "      }\n";

    @Test
    public void testCreatingKeyValues() {
        Map<String, String> map = new HashMap<String, String>();
        try {
            addKeys("", new ObjectMapper().readTree(json), map);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(map);
    }

    private void addKeys(String currentPath, JsonNode jsonNode, Map<String, String> map) {
        if (jsonNode.isObject()) {
            ObjectNode objectNode = (ObjectNode) jsonNode;
            Iterator<Map.Entry<String, JsonNode>> iter = objectNode.getFields();
            String pathPrefix = currentPath.isEmpty() ? "" : currentPath + ".";

            while (iter.hasNext()) {
                Map.Entry<String, JsonNode> entry = iter.next();
                // Customization here
                if (entry.getKey().equals("items")) {
                    ArrayNode arrayNode = (ArrayNode) entry.getValue();
                    for (int i = 0; i < arrayNode.size(); i++) {
                        addKeys(currentPath + entry.getKey() + "[" + i + "]", arrayNode.get(i).get("id"), map);
                    }
                } else {
                    addKeys(pathPrefix + entry.getKey(), entry.getValue(), map);
                }
            }
        } else if (jsonNode.isArray()) {
            ArrayNode arrayNode = (ArrayNode) jsonNode;
            for (int i = 0; i < arrayNode.size(); i++) {
                addKeys(currentPath + "[" + i + "]", arrayNode.get(i), map);
            }
        } else if (jsonNode.isValueNode()) {
            ValueNode valueNode = (ValueNode) jsonNode;
            map.put(currentPath, valueNode.asText());
        }
    }
}

Try understanding the format that you need, and then study the above code. It should give you the answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM