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 (i.e. "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.
Related
how can i create a JSON string from Json array of objects like below in Java using JSON object
{
header: [
{
"key" : "numberOfRecords",
"value" : "122"
"valueDataType" : "string"
},
{
"key" : "g_udit"
"value" : "1"
"valueDataType" : "string"
},
{
"key": "userNameId"
"value" : "155"
"valueDataType : "string"
}
]
}
expected JSON output requires only values
{
header :
{
"numberOfRecords" : "122",
"g_udit" : "1",
"userNameId" : "155"
}
}
Use JSON query language to transform the JSON structure. A single Josson query statement can do the job.
https://github.com/octomix/josson
Josson josson = Josson.fromJsonString(
"{" +
" \"header\": [" +
" {" +
" \"key\" : \"numberOfRecords\"," +
" \"value\" : \"122\"," +
" \"valueDataType\" : \"string\"" +
" }," +
" { " +
" \"key\" : \"g_udit\"," +
" \"value\" : \"1\"," +
" \"valueDataType\" : \"string\"" +
" }," +
" {" +
" \"key\": \"userNameId\"," +
" \"value\" : \"155\"," +
" \"valueDataType\" : \"string\"" +
" }" +
" ]" +
"}");
JsonNode node = josson.getNode("map(header.map(key::value).mergeObjects())");
Output
{
"header" : {
"numberOfRecords" : "122",
"g_udit" : "1",
"userNameId" : "155"
}
}
First of all you should use any json framework to read and write files. You can use jacskon-utils to use Jackson and make it much simpler to use.
Then you have to define the data classes for input and output types. And finally, convert the data.
#Getter
class InputData {
#JsonProperty("header")
private List<Header> headers;
#Getter
public static class Header {
private String key;
private String value;
private String valueDataType;
}
}
#Setter
class OutputData {
#JsonProperty("header")
private Map<String, String> headers;
}
public static void main(String... args) throws Exception {
InputData inputData = readData(new File("c:/in.json"));
OutputData outputData = createOutputData(inputData);
writeData(new File("c:/out.json"), outputData);
}
private static InputData readData(File file) throws Exception {
try (InputStream in = new FileInputStream(file)) {
return JacksonUtils.readValue(in, InputData.class);
}
}
private static void writeData(File file, OutputData outputData) throws Exception {
try (OutputStream out = new FileOutputStream(file)) {
JacksonUtils.prettyPrint().writeValue(outputData, out);
}
}
private static OutputData createOutputData(InputData inputData) {
Map<String, String> headers = new LinkedHashMap<>();
inputData.getHeaders().forEach(header -> headers.put(header.getKey(), header.getValue()));
OutputData outputData = new OutputData();
outputData.setHeaders(headers);
return outputData;
}
I have json file with such form:
{
"Region_1": {
"Area_1": {
"id": "id_1",
"email": "email_1"
},
"Area_2": {
"id": "id_2",
"email": "email_2"
}
},
"Region_2": {
"Area_1": {
"id": "id_1",
"email": "email_1"
},
"Area_2": {
"id": "id_2",
"email": "email_2"
}
}
}
I need to parse this structure using JSONObject, I have already code which parse this but not get Region_2 only.
Region_1 getting.
JSONObject obj = new JSONObject(fileData);
for (Map.Entry<String, Object> entry : obj.entrySet()) {
String region = entry.getKey().toString();
JSONObject areas = new JSONObject(entry.getValue().toString());
System.out.println("region: " + region);
List links = areas.entrySet().collect({ it ->
String area = it.getKey().toString();
System.out.println("area: " + area);
JSONObject areaData = new JSONObject(it.getValue().toString());
String code = areaData.getString("id");
String email = areaData.getString("email");
System.out.println("code: " + code.toString());
System.out.println("email: " + email.toString());
})
}
Why only first object takes from json file ?
Im trying to restructure duplicate json values in my JSON Structure and rearrange them using the simplest possible method.
I got to the point where I managed to get it stored in a map each time it loops over the JSONObject but from here how do I proceed to store the mapping to achieve my desired outcome? Thank you so much in advance.
public static void main(String[] args) throws JSONException {
String jsonString = "[{\"file\":[{\"fileRefNo\":\"AG/CSD/1\",\"status\":\"Active\"}],\"requestNo\":\"225V49\"},{\"file\":[{\"fileRefNo\":\"AG/CSD/1\",\"status\":\"Inactive\"}],\"requestNo\":\"225SRV\"},{\"file\":[{\"fileRefNo\":\"AG/CSD/2\",\"status\":\"Active\"}],\"requestNo\":\"225SRV\"}]" ;
JSONArray json = new JSONArray(jsonString);
Map<String, Object> retMap = new HashMap<String, Object>();
for (int i = 0; i < json.length(); i++ ) {
if(json != JSONObject.NULL) {
retMap = toMap(json.getJSONObject(i));
System.out.println(retMap + "retMap");
//{file=[{fileRefNo=AG/CSD/1, status=Active}], requestNo=225V49}retMap
//{file=[{fileRefNo=AG/CSD/1, status=Inactive}], requestNo=225SRV}retMap
//{file=[{fileRefNo=AG/CSD/2, status=Active}], requestNo=225SRV}retMap
}
}
}
public static Map<String, Object> toMap(JSONObject object) throws JSONException {
Map<String, Object> map = new HashMap<String, Object>();
Iterator<String> keysItr = object.keys();
while(keysItr.hasNext()) {
String key = keysItr.next();
Object value = object.get(key);
if(value instanceof JSONArray) {
value = toList((JSONArray) value);
}
else if(value instanceof JSONObject) {
value = toMap((JSONObject) value);
}
map.put(key, value);
}
return map;
}
public static List<Object> toList(JSONArray array) throws JSONException {
List<Object> list = new ArrayList<Object>();
for(int i = 0; i < array.length(); i++) {
Object value = array.get(i);
if(value instanceof JSONArray) {
value = toList((JSONArray) value);
}
else if(value instanceof JSONObject) {
value = toMap((JSONObject) value);
}
list.add(value);
}
return list;
}
Here is my initial JSONArray
[{
"file": [{
"fileRefNo": "AG/CSD/1",
"status": "Active"
}],
"requestNo": "225V49"
}, {
"file": [{
"fileRefNo": "AG/CSD/1",
"status": "Inactive"
}],
"requestNo": "225SRV"
}, {
"file": [{
"fileRefNo": "AG/CSD/2",
"status": "Active"
}],
"requestNo": "225SRV"
}]
Here is my desired outcome
[{
"file": [{
"fileRefNo": "AG/CSD/1",
"status": "Active"
}],
"requestNo": "225V49"
}, {
"file": [{
"fileRefNo": "AG/CSD/1",
"status": "Inactive"
},{
"fileRefNo": "AG/CSD/2",
"status": "Active"
}],
"requestNo": "225SRV"
}]
https://github.com/octomix/josson
Josson josson = Josson.fromJsonString(
"[{" +
" \"file\": [{" +
" \"fileRefNo\": \"AG/CSD/1\"," +
" \"status\": \"Active\"" +
" }]," +
" \"requestNo\": \"225V49\"" +
"}, {" +
" \"file\": [{" +
" \"fileRefNo\": \"AG/CSD/1\"," +
" \"status\": \"Inactive\"" +
" }]," +
" \"requestNo\": \"225SRV\"" +
"}, {" +
" \"file\": [{" +
" \"fileRefNo\": \"AG/CSD/2\"," +
" \"status\": \"Active\"" +
" }]," +
" \"requestNo\": \"225SRV\"" +
"}]");
JsonNode node = josson.getNode("group(requestNo, file).field(file.flatten(1))");
System.out.println(node.toPrettyString());
Output
[ {
"requestNo" : "225V49",
"file" : [ {
"fileRefNo" : "AG/CSD/1",
"status" : "Active"
} ]
}, {
"requestNo" : "225SRV",
"file" : [ {
"fileRefNo" : "AG/CSD/1",
"status" : "Inactive"
}, {
"fileRefNo" : "AG/CSD/2",
"status" : "Active"
} ]
} ]
I have a json in a JsonObject such as:
"customer": {
"full_name": "John John",
"personal": {
"is_active": "1",
"identifier_info": {
"hobbies": [
"skiing",
"traveling"
],
"user_id": "1234",
"office_id": "2345"
}
}
}
Is there a way to modify the JsonObject so as to remove the hobbies completely from the identifier_info and leave the rest untouched and then add the contents of hobbies the same way as the others? i.e.
"customer": {
"full_name": "John John",
"personal": {
"is_active": "1",
"identifier_info": {
"skiing":"expert",
"traveling":"rarely",
"user_id": "1234",
"office_id": "2345"
}
}
}
Find the full implementation for removing the JSON Array "hobbies" and to insert them in the parent JSON Object directly.
public class ProcessJSONString {
String data ="{\"customer\": { \n" +
" \"full_name\": \"John John\", \n" +
" \"personal\": { \n" +
" \"is_active\": \"1\", \n" +
" \"identifier_info\": { \n" +
" \"hobbies\": [ \n" +
" \"skiing\",\n" +
" \"traveling\"\n" +
" ], \n" +
" \"user_id\": \"1234\", \n" +
" \"office_id\": \"2345\"\n" +
" } \n" +
" } \n" +
"}} ";
public void processData() {
try {
JSONObject result = new JSONObject(data);
JSONObject customer = result.getJSONObject("customer");
JSONObject personal = customer.getJSONObject("personal");
JSONObject identifierInfo =
personal.getJSONObject("identifier_info");
JSONArray hobbies = identifierInfo.getJSONArray("hobbies");
identifierInfo.remove("hobbies");
//Under the assumption the tags will be added by the user, the code has been inserted.
identifierInfo.put("skiing","expert");
identifierInfo.put("traveling","rarely");
} catch (JSONException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ProcessJSONString instance = new ProcessJSONString();
instance.processData();
}
}
That should be no problem, using JsonObject's remove() method. It returns the removed JsonElement. Assuming the original json is a JsonObject called customer:
JsonObject identifierInfo = customer.getAsJsonObject("personal").getAsJsonObject("identifier_info");
JsonArray hobbies = (JsonArray) identifierInfo.remove("hobbies");
after that you can just add the hobbies to the identifierInfo and get the desired result:
for (JsonElement aHobby : hobbies) {
identifierInfo.addProperty(aHobby.getAsString(), "expert");
}
don't forget to add null checks as needed.
Given the following JSON response:
{
"status": "OK",
"regions": [
{
"id": "69",
"name": "North Carolina Coast",
"color": "#01162c",
"hasResorts": 1
},
{
"id": "242",
"name": "North Carolina Inland",
"color": "#01162c",
"hasResorts": 0
},
{
"id": "17",
"name": "North Carolina Mountains",
"color": "#01162c",
"hasResorts": 1
},
{
"id": "126",
"name": "Outer Banks",
"color": "#01162c",
"hasResorts": 1
}
]
}
I'm trying to create a List of Region objects. Here's a very abridged version of my current code:
JSONObject jsonObject = new JSONObject(response);
String regionsString = jsonObject.getString("regions");
Type listType = new TypeToken<ArrayList<Region>>() {}.getType();
List<Region> regions = new Gson().fromJson(regionsString, listType);
This is all working fine. However, I'd like to exclude the regions in the final List that hasResorts == 0. I realize I can loop through the actual JSONObjects and check them before calling fromJSON on each region. But I'm assuming there is a GSON specific way of doing this.
I was looking at the ExclusionStrategy(). Is there a simple way to implement this to JSON deserialization?
ExclusionStrategy won't help you since it works without the context of deserialization. Indeed, you can exclude only a specific kind of class. I think that best way of doing it is through custom deserialization. Here is what I mean (you can copy&paste&try immediately):
package stackoverflow.questions.q19912055;
import java.lang.reflect.Type;
import java.util.*;
import stackoverflow.questions.q17853533.*;
import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
public class Q19912055 {
class Region {
String id;
String name;
String color;
Integer hasResorts;
#Override
public String toString() {
return "Region [id=" + id + ", name=" + name + ", color=" + color
+ ", hasResorts=" + hasResorts + "]";
}
}
static class RegionDeserializer implements JsonDeserializer<List<Region>> {
public List<Region> deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
if (json == null)
return null;
ArrayList<Region> al = new ArrayList<Region>();
for (JsonElement e : json.getAsJsonArray()) {
boolean deserialize = e.getAsJsonObject().get("hasResorts")
.getAsInt() > 0;
if (deserialize)
al.add((Region) context.deserialize(e, Region.class));
}
return al;
}
}
/**
* #param args
*/
public static void main(String[] args) {
String json =
" [ "+
" { "+
" \"id\": \"69\", "+
" \"name\": \"North Carolina Coast\", "+
" \"color\": \"#01162c\", "+
" \"hasResorts\": 1 "+
" }, "+
" { "+
" \"id\": \"242\", "+
" \"name\": \"North Carolina Inland\", "+
" \"color\": \"#01162c\", "+
" \"hasResorts\": 0 "+
" }, "+
" { "+
" \"id\": \"17\", "+
" \"name\": \"North Carolina Mountains\", "+
" \"color\": \"#01162c\", "+
" \"hasResorts\": 1 "+
" }, "+
" { "+
" \"id\": \"126\", "+
" \"name\": \"Outer Banks\", "+
" \"color\": \"#01162c\", "+
" \"hasResorts\": 1 "+
" } "+
" ] ";
Type listType = new TypeToken<ArrayList<Region>>() {}.getType();
List<Region> allRegions = new Gson().fromJson(json, listType);
System.out.println(allRegions);
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(listType, new RegionDeserializer());
Gson gson2 = builder.create();
List<Region> regionsHaveResort = gson2.fromJson(json, listType);
System.out.println(regionsHaveResort);
}
}