How to convert HashMap to json Array in android? - java

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 );

Related

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

How to construct a JSON from this Map data

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.

Convert java object to a POJO style http parameter

I'm using playframework, is there any way to convert a java object into Play recognizable pojo parameter list?
For example I have two class
public class A{
B b;
String room;
}
public class B{
String name;
}
When I get a A instance a, I can change it into two parameters
a.room=myroom&a.b.name=myname
Do I have to travel through a json converted from that instance?
Thanks a lot.
I wrote a Util to convert Object to playframework friendly parameter list with jackson.databind
public static List<MutablePair> getPojoParam(Object base, Object obj, boolean firstLevel) {
List<MutablePair> ret = new ArrayList<MutablePair>();
String realBase = (firstLevel) ? (String) base : ("." + base);
if (obj instanceof Collection) {
int count = 0;
for (Object o : (Collection) obj) {
List<MutablePair> subPair = getPojoParam(base, o, false);
for (MutablePair p : subPair) {
p.left = realBase + "[" + (count++) + "]" + p.left;
ret.add(p);
}
}
} else if (obj instanceof Map) {
Map<Object, Object> map = (Map<Object, Object>) obj;
for (Object k : map.keySet()) {
List<MutablePair> subPair = getPojoParam(k, map.get(k), false);
for (MutablePair p : subPair) {
p.left = realBase + p.left;
ret.add(p);
}
}
} else {
ret.add(new MutablePair(realBase, obj));
}
return ret;
}
Usage:
ATest a = new ATest();
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> data = mapper.readValue(new Gson().toJson(a), Map.class);
List<MutablePair> ret = ObjectToPOJO.getPojoParam("source", data, true);
for (MutablePair key : ret) {
System.out.println(key.left + "=" + key.right);
}
I hope it's right.
Add dependencies to use MutablePair and jackson.databind
require:
- com.fasterxml.jackson.core -> jackson-databind 2.1.0
- org.apache.commons -> commons-lang3 3.1

How to convert nested List into multidimensional array?

In Java I want to convert a nested List which contains at the deepest level a uniform type into an multidimensional array of that type. For example, ArrayList<ArrayList<ArrayList<ArrayList<String>>>> into String[][][][]. I've tried several things and I only can obtain an array of objects like Object[][][][]. For 'simple lists' it seems that Apache Commons Lang does the work but I cannot figure out for nested cases.
Update:
In order to obtain a multidimensional array of Object type I'm using a recursive function so I cannot set the key type using toArray() see excerpt:
// the argument of this function is a (nested) list
public static Object convert(Object object) {
Object[] result = null;
List list = (List) object;
if (list != null) {
Object type = getElementType(list);
if (type instanceof List) {
int size = list.size();
result = new Object[size];
for (int counter = 0; counter < size; counter++) {
Object element = list.get(counter);
result[counter] = (element != null) ? convert(element) : null;
}
} else {
result = list.toArray();
}
}
return result;
}
private static Object getElementType(List list) {
Object result = null;
for (Object element : list) {
if (element != null) {
result = element;
break;
}
}
return result;
}
To create any kind of non-Object array, you need to pass a type key to the toArray method. This is because for generic types (e.g., ArrayList), the type argument is erased (so, at runtime, ArrayList<String> is treated as a plain ArrayList), whereas for arrays, the type is not.
It seems you already have the Object array creation sorted, so with that and the use of the type key, I think you're all sorted! :-)
This is the way that someone suggested to solved for String type. Cast2(List<?>) returns the multidimensional array. It may be generalized to use the class type as parameter. Thank you for your comments.
static int dimension2(Object object) {
int result = 0;
if (object instanceof List<?>) {
result++;
List<?> list = (List<?>) object;
for (Object element : list) {
if (element != null) {
result += dimension2(element);
break;
}
}
}
return result;
}
static Object cast2(List<?> l) {
int dim = dimension2(l);
if (dim == 1) {
return l.toArray(new String[0]);
}
int[] dims = new int[dimension2(l)];
dims[0] = l.size();
Object a = Array.newInstance(String.class, dims);
for (int i = 0; i < l.size(); i++) {
List<?> e = (List<?>) l.get(i);
if (e == null) {
Array.set(a, i, null);
} else if (dimension2(e) > 1) {
Array.set(a, i, cast2(e));
} else {
Array.set(a, i, e.toArray(new String[0]));
}
}
return a;
}
hehe, heres a answer too but i dunno if that really helps:
List<ArrayList<ArrayList<ArrayList<String>>>> x = new ArrayList<ArrayList<ArrayList<ArrayList<String>>>>();
public static void main(String[] args) throws MalformedURLException, IOException, SecurityException, NoSuchFieldException {
Type t = ((ParameterizedType)(jdomTEst.class.getDeclaredField("x").getGenericType())).getActualTypeArguments()[0];
int[] dims = new int[t.toString().split("List").length];
Object finalArray = Array.newInstance(String.class, dims);
System.out.println(finalArray);
}
this prints: [[[[Ljava.lang.String;#4e82701e
looks pretty messy but i love reflections :)
You can use transmorph :
ArrayList<ArrayList<ArrayList<ArrayList<String>>>> arrayList = new ArrayList<ArrayList<ArrayList<ArrayList<String>>>>();
/// populate the list ...
[...]
Transmorph transmorph = new Transmorph(new DefaultConverters());
String[][][][] array = transmorph.convert(arrayList, String[][][][].class);

Categories