How to construct a JSON from this Map data - java

I have a Map with a key and value as linked List as shown below
{Ice creams=[Cone,KoolCool(21), Stick,KoolCool(25)]}
With this i need to construct a following json
{
"name": "Ice creams",
"T2": [
{
"name": "Cone",
"T3": [
{
"name": "KoolCool",
"leaf": []
}
]
},
{
"name": "Stick",
"T3": [
{
"name": "KoolCool",
"leaf": []
}
]
}
]
}
Every comma seperated value will increment the T value
I am trying to apprach this with the below
For every key in the Map Access its value as LinkedList
From that LinkedList access split it and construct the json
Could anybody please let me know if there is a better way of doing this ??
package com.util;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
public class Test {
public static void main(String args[]) {
Map<String, LinkedList<String>> consilatedMapMap = new LinkedHashMap<String, LinkedList<String>>();
LinkedList<String> values = new LinkedList<String>();
values.add("Cone,KoolCool(21)");
values.add("Stick,KoolCool(25)");
consilatedMapMap.put("Ice creams", values);
/*
* for (Map.Entry<String, LinkedList<String>> consilMap :
* consilatedMapMap.entrySet()) {
*
* String t1Category = consilMap.getKey(); LinkedList<String>
* consiladatedList = consilMap.getValue();
*
*
* for(int i=0;i<consiladatedList.size();i++) { String result =
* consiladatedList.get(i);
*
* String spliter[] = result.split(",");
*
* for(int j=0;j<spliter.length;j++) { System.out.println(spliter[j]); }
*
* }
*
* }
*/
}
}

I believe you're overcomplicating this - autoincremented names... The JSON structure doesn't match the Java structure... JSON generated partly by object structure, partly by parsing strings within it... even though you say "Every comma seperated value will increment the T value" this is obviously not true from the example.
Nevertheless... this is possible - even just using org.json (not sure why people keep suggesting GSON as a fix all to this...)
The primary idea here is to make a method for each part you need to generate, and pass the "level" around to generate the appropriate "Tn" property when you need it.
public class Test {
private static JSONObject processString(String data, int level) throws JSONException {
JSONObject json = new JSONObject();
int index = data.indexOf(',');
String name = data;
String remainder = "";
if (index < 0) {
index = name.indexOf('(');
if (index > 0) {
name = data.substring(0, index);
}
} else {
name = data.substring(0, index);
remainder = data.substring(name.length() + 1);
}
json.put("name", name);
JSONArray a = new JSONArray();
if (remainder.length() > 0) {
a.put(processString(remainder, level + 1));
json.put("T" + level, a);
} else {
json.put("leaf", a);
}
return json;
}
private static JSONArray processList(List<String> list, int level) throws JSONException {
JSONArray json = new JSONArray();
for (String data : list) {
json.put(processString(data, level));
}
return json;
}
private static JSONObject processMap(Map<String>, List<String>> map, int level) throws JSONException {
JSONObject json = new JSONObject();
for (String key : map.keySet()) {
json.put("name", key);
json.put("T" + level, processList(map.get(key), level + 1));
}
return json;
}
public static void main(String args[]) {
Map<String, List<String>> consilatedMapMap = new LinkedHashMap<String, List<String>>();
List<String> values = new LinkedList<String>();
values.add("Cone,KoolCool(21)");
values.add("Stick,KoolCool(25)");
consilatedMapMap.put("Ice creams", values);
try {
int level = 2;
JSONObject json = processMap(consilatedMapMap, level);
} catch(JSONException x) {
x.printStackTrace();
System.exit(-1);
}
}

There is a utility library called Gson on Google code.You can check it out here
For some simple examples visit this

Look at folowing code:
Map<String, LinkedList<String>> consilatedMapMap = new LinkedHashMap<String, LinkedList<String>>();
LinkedList<String> values = new LinkedList<String>();
values.add("Cone,KoolCool(21)");
values.add("Stick,KoolCool(25)");
consilatedMapMap.put("Ice creams", values);
Gson gson=new Gson();
String jsonElement=gson.toJson(consilatedMapMap);
System.out.println(jsonElement);
Output
{"Ice creams":["Cone,KoolCool(21)","Stick,KoolCool(25)"]}
As you can see from the code and it's output, Gson library would convert your data structure to a json string.
All you need is this Gson library.

Related

Java - sort JSONArray based on two attribute values

I have a JSONArray as below,
JSONArray dataArray = new JSONArray();
dataArray = [
{
"name": "name1",
"row": 1,
"value": 20
},
{
"name": "name2",
"row": 1,
"value": 10
},
{
"name": "name3",
"row": 2,
"value": 10
},
{
"name": "name4",
"row": 3,
"value": 30
},
{
"name": "name5",
"row": 3,
"value": 10
}
]
I need to compare the row attribute, if same, need to compare value attribute and sort the object in the array.
Tried with Java comparator, but couldn't make it work. Can somebody please help?
for(int i = 0; i < dataArray.size(); i++) {
elementList.add((JSONObject) dataArray.get(i));
}
Long row1 = null;
for (JSONObject obj : elementList) {
if(row1 == null) {
row1 = (Long) ((JSONObject) obj.get("row"));
}
else {
Long row2 = (Long) ((JSONObject) obj.get("row"));
if(row2 == row1) {
//call the comparator, but how to pass two objects?
}
row1 = row2;
}
}
It would be easy to extend this answer to match your scenario
But instead of
return valA.compareTo(valB);
you should do
int comp = valA.compareTo(valB);
if (comp == 0){
String valC = (String) a.get(KEY_NAME2);
String valD = (String) b.get(KEY_NAME2);
return valC.compareTo(valD);
} else {
return comp;
}
So it should be the following.
JSONArray sortedJsonArray = new JSONArray();
List<JSONObject> jsonValues = new ArrayList<JSONObject>();
for (int i = 0; i < dataArray.length(); i++) { // <---- dataArray is the input that you have
jsonValues.add(dataArray.getJSONObject(i));
}
Collections.sort( jsonValues, new Comparator<JSONObject>() {
//You can change "Name" with "ID" if you want to sort by ID
private static final String KEY_NAME1 = "row";
private static final String KEY_NAME2 = "value";
#Override
public int compare(JSONObject a, JSONObject b) {
String valA = new String();
String valB = new String();
try {
valA = (String) a.get(KEY_NAME1);
valB = (String) b.get(KEY_NAME1);
}
catch (JSONException e) {
//do something
}
int comp = valA.compareTo(valB);
if (comp == 0){
String valC = (String) a.get(KEY_NAME2);
String valD = (String) b.get(KEY_NAME2);
return valC.compareTo(valD);
} else {
return comp;
}
}
});
Edit: changed into KEY_NAME1 = "row"; to match the new question requirement
A simpler approach here:
You could convert your JSON string to List<YourObject> by using Jackson's ObjectMapper
List<YourObject> list = objectMapper.readValue(json, new TypeReference<List<YourObject>>(){});
Then use Collections.sort and Comparator to sort this list. You can also implement a custom Comparator to sort a list by multiple attributes depending on your situation.
list.sort(Comparator.comparing(YourObject::getRow)
.thenComparing(YourObject::getValue));
Let's assume you deserialize your json data into objects like
public class DataRow {
private String name;
private int row;
private int value;
// Getter, Setter, Constructor what ever needed
}
Then you can work with a list and stream like:
List<DataRow> datarows = //... read data from json
List<DataRow> sorted = datarows.stream()
.sorted(Comparator.comparing(DataRow::getRow).thenComparingInt(DataRow::getValue)).toList();

Java Jackson- Compare two JSONs ignoring order of keys and elements in arrays

I have two JSON strings which I want to compare.
I want neither the order of the keys to matter or the order of elements in an array.
However I do want an extra field to be considered "not equal"
Non strict mode with JSONAssert seems like it fits the bill except for an extra field being considered equal "http://jsonassert.skyscreamer.org/cookbook.html"
If at all possible I would like to avoid pulling in extra dependancies. I already have jackson in my project
I have 2 ideas how to do it.
Is to write java objects and serialize it, and write own equals method.
Is to serialize it to Map<Object, Object> and compare 2 map.
String json1 = "{...}"
String json2= "{...}"
Object json1Object = objectMapper.readValue(json1, Object.class);
Object json2Object = objectMapper.readValue(json2, Object.class);
Assertions.assertEquals(json1Object, json2Object);
Assertions.assertTrue(json1Object.equals(json2Object));
So you probably have only one option. Write own comparator.
My quick solution:
#Test
public void comparingJsonTest4() throws JsonProcessingException {
String json1 = "{\"id\": 1, \"name\": \"test\", \"cars\": [\"Ford\", \"BMW\", \"Fiat\"]}";
String json2 = "{\"name\": \"test\", \"id\": 1, \"cars\": [\"BMW\", \"Ford\", \"Fiat\"]}";
ObjectMapper objectMapper = new ObjectMapper();
JsonNode json1Node = objectMapper.readTree(json1);
JsonNode json2Node = objectMapper.readTree(json2);
Assertions.assertEquals(0, new ComparatorWithoutOrder().compare(json1Node, json2Node));
}
class ComparatorWithoutOrder implements Comparator<JsonNode> {
#Override
public int compare(JsonNode o1, JsonNode o2) {
if(o1 == o2) {
return 0;
}
if(o1.getClass() != o2.getClass()) {
return -1;
}
if(o1.getClass() == ObjectNode.class) {
List<String> o1FieldNames = new ArrayList<>();
o1.fieldNames().forEachRemaining(o1FieldNames::add);
List<String> o2FieldNames = new ArrayList<>();
o2.fieldNames().forEachRemaining(o2FieldNames::add);
if(o1FieldNames.size() != o2FieldNames.size()) {
return -1;
}
if(!o2FieldNames.containsAll(o1FieldNames) || !o1FieldNames.containsAll(o2FieldNames)) {
return -1;
}
for (String o1FieldName : o1FieldNames) {
if (!(compare(o1.get(o1FieldName), o2.get(o1FieldName)) == 0)) {
return -1;
}
}
return 0;
}
if(o1.getClass() == ArrayNode.class) {
List<JsonNode> o1Children = new ArrayList<>();
o1.elements().forEachRemaining(o1Children::add);
List<JsonNode> o2Children = new ArrayList<>();
o2.elements().forEachRemaining(o2Children::add);
if(o1Children.size() != o2Children.size()) {
return -1;
}
for (JsonNode c1 : o1Children) {
boolean found = false;
for (JsonNode c2 : o2Children) {
if (compare(c1, c2) == 0) {
found = true;
break;
}
}
if (!found) {
return -1;
}
}
return 0;
}
return o1.equals(o2) ? 0 : -1;
}
}
At the beginning I wanted to use something like this:
json1Node.equals(new ComparatorWithoutOrder(), json2Node);
but thre was a problem to propoer handle ArrayNode inside ObjectNode. So if you want, you could skip implements Comparator<JsonNode>, because finally I don't use this functionality.

How to convert JSONObject to new Map for all its keys using iterator java

I have a JSONObject
{"2016":{"12":{"20":{"19":{"DonationTime":11111111111,"Donation":10}}}}}
I want to convert it to new map with each keys
int i = 0;
for (Iterator<String> keysItr = object.keySet().iterator(); keysItr.`hasNext(); i++) {
String key = keysItr.next();
Object value = object.get(key);
if(value instanceof JSONObject) {
value = toMap((JSONObject) value);
map.put(key, value);
}
}
SOP(map); //but here i want to get 4 maps
}
I want to get 4 maps like
hourMap[19] = "{"DonationTime":11111111111,"Donation":10}";
dayMap[20] = "{"19":{"DonationTime":11111111111,"Donation":10}}";
monthMap[12] = "{"12":{"20":{"19":{"DonationTime":11111111111,"Donation":10}}}";
yearMap[2016] = "{"12":{"20":{"19":{"DonationTime":11111111111,"Donation":10}}}";
I am using for loop yet i am unable to get incremented value for i.
Well u can simply convert the JSON object into a map and then from there u can easily take out the four maps u interested in
here is a simple example
(watch out the code below on a big JSON graph can cause u some problems since it is a recursion based conversion)
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.*;
public class JsonMapConverter {
public static void main(String... x) throws Exception {
String jsonString = "{\"2016\":{\"12\":{\"20\":{\"19\":{\"DonationTime\":11111111111,\"Donation\":10}}}}}";
JSONObject json = new JSONObject(jsonString);
Map<String,Object> yearMap = toMap(json);
String year = yearMap.keySet().iterator().next();
Map<String,Object> monthMap = ((Map<String, Object>) yearMap.get(year));
String month = monthMap.keySet().iterator().next();
Map<String,Object> dayMap = (Map<String, Object>) monthMap.get(month);
String day = dayMap.keySet().iterator().next();
Map<String,Object> hourMap = (Map<String, Object>) dayMap.get(day);
System.out.println(yearMap);
System.out.println(monthMap);
System.out.println(dayMap);
System.out.println(hourMap);
}
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;
}
}
for JSON to map conversion i use the code from this answer (Convert a JSON String to a HashMap)
the code was written based on the json string, u may adjust the code according to your needs in case of multiple years,month and days presents in the json

Removing values from edges

I have data in following format
String [] data = new String[]{"-166444026 0 file 20130801",
"-166444026 0 file 20130802",
"-166444027 0 file 20130802"};
These are tab seperated strings.
Now..
So we have
key, value,type,date.
What I want is to keep latest unique keys in the list.
So for example...
The output of this operation should be...
["-166444026 0 file 20130802",
"-166444027 0 file 20130802"];
Because -166444026 is present twice but the one i removed has date of 20130801 and this one has a later date?
I wrote the code.. but this just returns everything.(I thought it was suppose to remove.. but it isnt..)??
Any clues?
package org.random_scripts;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.json.simple.JSONObject;
public class Regex {
private static boolean alreadyExists(Map<String, Long> dict, String key) {
if(dict.containsKey(key))
return true;
return false;
}
private static void removeEdge(ArrayList<JSONObject>edgeList, String key) {
for(JSONObject edge:edgeList) {
if (edge.get("destination").equals(key))
edge.remove(key);
}
}
public static void main(String[] args) {
String [] data = new String[]{"-166444026 0 file 20130801",
"-166444026 0 file 20130802",
"-166444026 0 file 20130802"};
try {
String key = "185479485";
JSONObject jsn = new JSONObject();
jsn.put("source", key.toString());
ArrayList<JSONObject> edges = new ArrayList<JSONObject>();
Map<String, Long> tracker = new HashMap<String, Long>();
for (int i=0; i < data.length; i++) {
String value = data[i];
//edgeString+= value.toString()+",";
String[] typeChunks = value.toString().split("\t");
String destination = typeChunks[0];
Double reputation = Double.parseDouble(String.valueOf(typeChunks[1]));
System.out.println(tracker.values().toString());
JSONObject edgeJson = new JSONObject();
Long date = Long.valueOf(typeChunks[3]);
if(alreadyExists(tracker,destination)) {
Long prev_date = tracker.get(destination);
System.out.println(true);
if (date > prev_date) {
//remove edge
removeEdge(edges,destination);
System.out.println("edges are" + edges.toString());
}
}
else {
tracker.put(destination, date);
}
edgeJson.put("destination", destination);
edgeJson.put("reputation", reputation);
edgeJson.put("type", typeChunks[2]);
edges.add(edgeJson);
}
jsn.put("edgelist", edges);
System.out.println(jsn.toJSONString());
//context.write(NullWritable.get(), new Text(jsn.toJSONString()));
//edgeString = edgeString.substring(0,edgeString.length()-1);
//edgeString+="]";
}
catch (Exception e) {
System.out.println("Exceptiom");
//context.write(NullWritable.get(),new Text(s) );
}
}
}
Use a HashMap, then assign each line to a key in the HashMap.
The HashMap will retain only the latest assigned value, so you can decide if you want to reassign it or not depending on its date.
If you need to preserve the original order of the lines, you can use a LinkedHashMap which preserves insertion order.
Hope it helps.
Search a last word with a regexp and then just iterate the array?
String key = data[data.length - 1].replaceAll(".*\\s", "");
for (int i = 0; i < data.length; i++) {
if (data[i].endsWith(key)) {
System.out.println(data[i]);
}
}
Out:
-166444026 0 file 20130802
-166444027 0 file 20130802

How to convert HashMap to json Array in android?

I want to convert HashMap to json array my code is as follow:
Map<String, String> map = new HashMap<String, String>();
map.put("first", "First Value");
map.put("second", "Second Value");
I have tried this but it didn't work. Any solution?
JSONArray mJSONArray = new JSONArray(Arrays.asList(map));
Try this,
public JSONObject (Map copyFrom)
Creates a new JSONObject by copying all name/value mappings from the given map.
Parameters
copyFrom a map whose keys are of type String and whose values are of supported types.
Throws
NullPointerException if any of the map's keys are null.
Basic usage:
JSONObject obj=new JSONObject(yourmap);
get the json array from the JSONObject
Edit:
JSONArray array=new JSONArray(obj.toString());
Edit:(If found Exception then You can change as mention in comment by #krb686)
JSONArray array=new JSONArray("["+obj.toString()+"]");
Since androiad API Lvl 19, you can simply do new JSONObject(new HashMap()). But on older API lvls you get ugly result(simple apply toString to each non-primitive value).
I collected methods from JSONObject and JSONArray for simplify and beautifully result. You can use my solution class:
package you.package.name;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;
public class JsonUtils
{
public static JSONObject mapToJson(Map<?, ?> data)
{
JSONObject object = new JSONObject();
for (Map.Entry<?, ?> entry : data.entrySet())
{
/*
* Deviate from the original by checking that keys are non-null and
* of the proper type. (We still defer validating the values).
*/
String key = (String) entry.getKey();
if (key == null)
{
throw new NullPointerException("key == null");
}
try
{
object.put(key, wrap(entry.getValue()));
}
catch (JSONException e)
{
e.printStackTrace();
}
}
return object;
}
public static JSONArray collectionToJson(Collection data)
{
JSONArray jsonArray = new JSONArray();
if (data != null)
{
for (Object aData : data)
{
jsonArray.put(wrap(aData));
}
}
return jsonArray;
}
public static JSONArray arrayToJson(Object data) throws JSONException
{
if (!data.getClass().isArray())
{
throw new JSONException("Not a primitive data: " + data.getClass());
}
final int length = Array.getLength(data);
JSONArray jsonArray = new JSONArray();
for (int i = 0; i < length; ++i)
{
jsonArray.put(wrap(Array.get(data, i)));
}
return jsonArray;
}
private static Object wrap(Object o)
{
if (o == null)
{
return null;
}
if (o instanceof JSONArray || o instanceof JSONObject)
{
return o;
}
try
{
if (o instanceof Collection)
{
return collectionToJson((Collection) o);
}
else if (o.getClass().isArray())
{
return arrayToJson(o);
}
if (o instanceof Map)
{
return mapToJson((Map) o);
}
if (o instanceof Boolean ||
o instanceof Byte ||
o instanceof Character ||
o instanceof Double ||
o instanceof Float ||
o instanceof Integer ||
o instanceof Long ||
o instanceof Short ||
o instanceof String)
{
return o;
}
if (o.getClass().getPackage().getName().startsWith("java."))
{
return o.toString();
}
}
catch (Exception ignored)
{
}
return null;
}
}
Then if you apply mapToJson() method to your Map, you can get result like this:
{
"int": 1,
"Integer": 2,
"String": "a",
"int[]": [1,2,3],
"Integer[]": [4, 5, 6],
"String[]": ["a","b","c"],
"Collection": [1,2,"a"],
"Map": {
"b": "B",
"c": "C",
"a": "A"
}
}
A map consists of key / value pairs, i.e. two objects for each entry, whereas a list only has a single object for each entry. What you can do is to extract all Map.Entry<K,V> and then put them in the array:
Set<Map.Entry<String, String> entries = map.entrySet();
JSONArray mJSONArray = new JSONArray(entries);
Alternatively, sometimes it is useful to extract the keys or the values to a collection:
Set<String> keys = map.keySet();
JSONArray mJSONArray = new JSONArray(keys);
or
List<String> values = map.values();
JSONArray mJSONArray = new JSONArray(values);
Note: If you choose to use the keys as entries, the order is not guaranteed (the keySet() method returns a Set). That is because the Map interface does not specify any order (unless the Map happens to be a SortedMap).
This is the Simplest Method.
Just use
JSONArray jarray = new JSONArray(hashmapobject.toString);
You can use
JSONArray jarray = JSONArray.fromObject(map );

Categories