List<Map<String,Object>> to org.json.JSONObject? - java

List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
Map<String, Object> map = new HashMap<String, Object>();
map.put("abc", "123456");
map.put("def", "hmm");
list.add(map);
JSONObject json = new JSONObject(list);
try {
System.err.println(json.toString(2));
} catch (JSONException e) {
e.printStackTrace();
}
What's wrong with this code?
The output is:
{"empty": false}

public String listmap_to_json_string(List<Map<String, Object>> list)
{
JSONArray json_arr=new JSONArray();
for (Map<String, Object> map : list) {
JSONObject json_obj=new JSONObject();
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
try {
json_obj.put(key,value);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
json_arr.put(json_obj);
}
return json_arr.toString();
}
alright, try this~ This worked for me :D

List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
Map<String, Object> map = new HashMap<String, Object>();
map.put("abc", "123456");
map.put("def", "hmm");
list.add(map);
// it's wrong JSONObject json = new JSONObject(list);
// if u use list to add data u must be use JSONArray
JSONArray json = JSONArray.fromObject(list);
try {
System.err.println(json.toString(2));
} catch (JSONException e) {
e.printStackTrace();
}

You need to end up with a JSONArray (corresponding to the List) of JSONObjects (the Map).
Try declaring the json variable as a JSONArray instead of a JSONObject (I believe the JSONArray constructor will do the right thing).

Also: you could consider using one of other parsers from json.org's list: most of them allow your Json "objects" and "arrays" to map natively to java.util.Maps and java.util.Lists; or in some cases to real Java objects too.
My recommendation would be Jackson, http://jackson.codehaus.org/Tutorial
which allows for mapping to List/Map/Integer/String/Boolean/null, as well as to real Beans/POJOs. Just give it the type and it maps data to you, or writes Java objects as Json.
Others like "json-tools" from berlios, or google-gson also expose similar functionality.

You have a map nested inside a list. you are trying to call the Map without ever iterating through the list first. JSON sometimes feels like magic but in fact it is not.
I'll post some code in a moment.
It would be more consistent with JSON to make a Map of Maps instead of a List of Maps.
JSONObject json = new JSONObject(list);
Iterator<?> it = json.keys();
while (keyed.hasNext()) {
String x = (String) it.next();
JSONObject jo2 = new JSONObject(jo.optString(x));
}

This worked for me:
List<JSONObject> jsonCategories = new ArrayList<JSONObject>();
JSONObject jsonCategory = null;
for (ICategory category : categories) {
jsonCategory = new JSONObject();
jsonCategory.put("categoryID", category.getCategoryID());
jsonCategory.put("desc", category.getDesc());
jsonCategories.add(jsonCategory);
}
try {
PrintWriter out = response.getWriter();
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
_log.info(jsonCategories.toString());
out.write(jsonCategories.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

If you are using org.json.simple.JSONArray
(https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple/1.1.1)
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
Map<String, Object> map = new HashMap<String, Object>();
map.put("abc", "123456");
map.put("def", "hmm");
list.add(map);
JSONArray jsonArray = new JSONArray();
jsonArray.addAll(listOfMaps);

You can do it using both:
JSONArray directly as,
String toJson(Collection<Map<String, Object>> list)
{
return new JSONArray(list).toString();
}
Or by iterating the list with Java8 (like #ShadowJohn solution):
String toJson(Collection<Map<String, Object>> list)
{
return new JSONArray(
list.stream()
.map((map) -> new JSONObject(map))
.collect(Collectors.toList()))
.toString();
}

Related

Android - Save Map<String, Object[]> to file

How can I save this kind of map to file? (it should work for an android device too)
I tried:
Properties properties = new Properties();
for (Map.Entry<String, Object[]> entry : map.entrySet()) {
properties.put(entry.getKey(), entry.getValue());
}
try {
properties.store(new FileOutputStream(context.getFilesDir() + MainActivity.FileName), null);
} catch (IOException e) {
e.printStackTrace();
}
And I get:
class java.util.ArrayList cannot be cast to class java.lang.String (java.util.ArrayList and java.lang.String are in module java.base of loader 'bootstrap')
What should I do?
I was writing an answer based on String values serialization when I realized for your error that perhaps some value can be an ArrayList... I honestly don't fully understand the reasoning behind the error (of course, it is a cast, but I don't understand the java.util.ArrayList part)...
In any case, the problem is happening when you try storing your properties and it tries to convert your Object[] to String for saving.
In my original answer I suggested you to manually join your values when generating your file. It is straightforward with the join method of the String class:
Properties properties = new Properties();
for (String key : map.keySet()) {
Object[] values = map.get(key);
// Perform null checking
String value = String.join(",", values);
properties.put(key, value);
}
try {
properties.store(new FileOutputStream(context.getFilesDir() + MainActivity.FileName), null);
} catch (IOException e) {
e.printStackTrace();
}
For reading your values, you can use split:
Properties properties = new Properties();
Map<String, String> map = new HashMap<>();
InputStream in = null;
try {
in = new FileInputStream(context.getFilesDir() + MainActivity.FileName);
properties.load(in);
for (String key : properties.stringPropertyNames()) {
String value = properties.getProperty(k);
// Perform null checking
String[] values = value.split(",");
map.put(key, value);
}
} catch (Throwable t) {
t.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
But I think you have a much better approach: please, just use the Java builtin serialization mechanisms to save and restore your information.
For saving your map use ObjectOutputStream:
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(context.getFilesDir() + MainActivity.FileName))){
oos.writeObject(map);
}
You can read your map back as follows:
Map<String, Object> map;
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(context.getFilesDir() + MainActivity.FileName))){
map = (Map)ois.readObject();
}
If all the objects stored in your map are Serializables this second approach is far more flexible and it is not limited to String values like the first one.

Convert set to json array using java 8

Following is my code can it be optimized for java 8 and can it be more efficient?
public String LanguageString(Set<Locale> languageSet) throws Exception {
JSONObject json = new JSONObject();
JSONObject tempj = new JSONObject();
JSONArray jArr = new JSONArray();
try {
for (Locale locale : languageSet) {
if (locale != null) {
tempj = new JSONObject();
tempj.put("lcode", locale.toLanguageTag());
tempj.put("ldisplay", locale.getDisplayName());
jArr.put(tempj);
}
}
json.put("root", jArr);
} catch (JSONException e) {
//
}
return json.toString();
}
If you want to use Java 8 and Stream API you can use stream, map and reduce to create your final JSONObject, e.g.
public static String languageStringUsingStream(Set<Locale> locales) {
return new JSONObject()
.put("root", locales.stream()
.map(locale -> new JSONObject()
.put("lcode", locale.toLanguageTag())
.put("ldisplay", locale.getDisplayName(Locale.ENGLISH))
)
.reduce(new JSONArray(), JSONArray::put, (a, b) -> a))
.toString();
}
Here you can find a complete example:
https://gist.github.com/wololock/27bd296fc894f6f4594f997057218fb3

Unable to set json string to TextView in onPostExecute in asyncTask

The problem that I'm facing right now is I simply want to set the string data from a json array in onPostExecute(). I skeemed through many tutorials on it, however, I am unable to set the Text that resides in the MainActivity. I've added the sample code below . I wonder if the data is wrong .
#SuppressWarnings("unchecked")
protected void onPostExecute(JSONObject jsonobject) {
try {
jsonarray = jsonobject.getJSONArray("grape");
outerjson = jsonarray;
String ids = jsonobject.optString("id");
String tpes = jsonobject.optString("type");
for (int i = 0; i < jsonarray.length(); i++) {
HashMap<String, String> map = new HashMap<String, String>();
jsonobject = jsonarray.getJSONObject(i);
String str = "";}
// Step 3.
map1 = new HashMap<String, String>();
// this is the last step 4.
try {
JSONArray jArray = new JSONArray(str);
for (int i = 0; i < jArray.length(); i++) {
JSONObject json = null;
json = jArray.getJSONObject(i);
map1.put("id", json.getString("id"));
map1.put("type", json.getString("type"));
}
result.setText(jsonarray.toString());
///set the json in here
}catch (JSONException e) {}
} catch (JSONException e) {}
progressDialog.dismiss();
}
Not enough information, but I will try:
Make your code cleaner by using a container entity: MyData data = gson.fromJson(jsonobject, MyData.class).
Do not ignore exceptions
Make sure you are calling result.setText(string); within a main UI thread
Follow these 3 steps and, find the error, you will.

how to compare array from sqlite with contents with json array

Hi I´m having a problems with the best strategy to compare an array from an sqlite database and a json array coming from a webservice response . Please tell me the best way to compare this two arrays . Here is my code :
public void getAllElements() {
Map<String, String> map = new HashMap<String, String>();
try {
//select all query
db.open();
Cursor cc= db.getAllEntries();
try {
// looping through all rows and adding to list
if (cc.moveToFirst()) {
do {
map.put("ID",cc.getString(cc.getColumnIndex(DbHelper.ENTRY_ID)));
} while (cc.moveToNext());
}
} finally {
try { cc.close(); } catch (Exception ignore) {}
}
} finally {
try { db.close(); } catch (Exception ignore) {}
}
// return list
}
protected String doInBackground(String... params) {
// Creating service handler class instance
JSONParser jParser = new JSONParser();
DefaultHttpClient client = new DefaultHttpClient(); // Thread
String uri = "url";
HttpGet httpget = new HttpGet(uri);
httpget.setHeader("Cookie", cookie);
try {
response = client.execute(httpget);
// response
String res = EntityUtils.toString(response.getEntity());
// jarray with the json responde
jArr = new JSONArray(res);
System.out.println("response" + jArr);
for (int i = 0; i < jArr.length(); i++) {
// create json object
JSONObject jsonObject = jArr.getJSONObject(i);
// easy parse fields
String vid = jsonObject.getString("vid");
String nid = jsonObject.getString("nid");
// uid value
String field_text = jsonObject.getString("field_text");
String field_edit_ts = jsonObject.getString("field_editts");
String field_deleted_flag = jsonObject.getString("field_deleted");
String field_device_name = jsonObject.getString("field_devicename");
String field_creation_ts = jsonObject.getString("field_creationts");
String field_device_key = jsonObject.getString("field_devicekey");
}
} catch(Exception e){
}
}
I'd recommend wrapping both your Database and your JSON data in a class and implementing the equals(Object) method.
For your JSON data, once you have a class (as above), I'd use GSON (https://code.google.com/p/google-gson/) to convert directly to Objects
Then for your comparison, convert either your database or JSON data into a List (something from Collections, or a HashTable/HashMap (quicker for searching)) and use the Collections.contains(Object) (on the List) method and a contains count which you compare against the list's size. Here's an example, fill in the blanks:
List<YourObject> dbDataList = new ArrayList<YourObject>(Arrays.asList(yourDatabaseDataArray));
int containsCount = 0;
for (YourObject o : yourJsonDataArray){
if (dbDataList.contains(o))
containsCount ++;
}
// Success condition is up to you, I'm just comparing the sizes
if (containsCount == dbDataList.size()){
// Success!
} else {
// Failure
}
Map<String, String> map = new HashMap<String, String>();
You are creating HasMap which contains two string-variable(key and value). It is possible to search the values with keys for exemple but you cannot sort HashMap. (Array)List could be sorted, as Artyom said.
map.put("ID",cc.getString(cc.getColumnIndex(DbHelper.ENTRY_ID)));
You are putting string "ID" to the key of every value of the map. Change that to List and sort it with Collections.sort(list,Comparator).
You could create class to save state of data you have got and override method equals for compare in your class.
Further, for save data use ArrayList.
For compare used next code.
Collection<YourObject> one= new ArrayList(Arrays.asList(obj1, obj2, obj3));
Collection<YourObject> two = new ArrayList(Arrays.asList(obj1, obj2, obj3));
one.equals(two)

How do I clone an org.json.JSONObject in Java?

Is there a way to clone an instance of org.json.JSONObject without stringifying it and reparsing the result?
A shallow copy would be acceptable.
Easiest (and incredibly slow and inefficient) way to do it
JSONObject clone = new JSONObject(original.toString());
Use the public JSONObject(JSONObject jo, java.lang.String[] names) constructor and the public static java.lang.String[] getNames(JSONObject jo) method.
JSONObject copy = new JSONObject(original, JSONObject.getNames(original));
Cause $JSONObject.getNames(original) not accessible in android,
you can do it with:
public JSONObject shallowCopy(JSONObject original) {
JSONObject copy = new JSONObject();
for ( Iterator<String> iterator = original.keys(); iterator.hasNext(); ) {
String key = iterator.next();
JSONObject value = original.optJSONObject(key);
try {
copy.put(key, value);
} catch ( JSONException e ) {
//TODO process exception
}
}
return copy;
}
But remember it is not deep copy.
For Android developers, the simplest solution without using .getNames is:
JSONObject copy = new JSONObject();
for (Object key : original.keySet()) {
Object value = original.get(key);
copy.put(key, value);
}
Note: This is a only a shallow copy
the fastest + minimal way I found is this. it does deep copy.
JSONObject clone= new JSONObject(original.toMap());
I know the asker said
A shallow copy would be acceptable.
but I think that does not rule out if the solution will do deep copy.
Update: the toMap() function is not available in Android. but the org.json library available on maven under groupId org.json has it: https://search.maven.org/artifact/org.json/json/20210307/bundle
Couldn't find an existing deep clone method for com.google.gwt.json.client.JSONObject but the implementation should be few lines of code, something like:
public static JSONValue deepClone(JSONValue jsonValue){
JSONString string = jsonValue.isString();
if (string != null){return new JSONString(string.stringValue());}
JSONBoolean aBoolean = jsonValue.isBoolean();
if (aBoolean != null){return JSONBoolean.getInstance(aBoolean.booleanValue());}
JSONNull aNull = jsonValue.isNull();
if (aNull != null){return JSONNull.getInstance();}
JSONNumber number = jsonValue.isNumber();
if (number!=null){return new JSONNumber(number.doubleValue());}
JSONObject jsonObject = jsonValue.isObject();
if (jsonObject!=null){
JSONObject clonedObject = new JSONObject();
for (String key : jsonObject.keySet()){
clonedObject.put(key, deepClone(jsonObject.get(key)));
}
return clonedObject;
}
JSONArray array = jsonValue.isArray();
if (array != null){
JSONArray clonedArray = new JSONArray();
for (int i=0 ; i < array.size() ; ++i){
clonedArray.set(i, deepClone(array.get(i)));
}
return clonedArray;
}
throw new IllegalStateException();
}
*Note:*I haven't tested it yet!
In case anyone comes here looking for a deep clone for org.google.gson, since they don't expose their deepClone() method this is what I came up with...
public static JsonElement deepClone(JsonElement el){
if (el.isJsonPrimitive() || el.isJsonNull())
return el;
if (el.isJsonArray()) {
JsonArray array = new JsonArray();
for(JsonElement arrayEl: el.getAsJsonArray())
array.add(deepClone(arrayEl));
return array;
}
if(el.isJsonObject()) {
JsonObject obj = new JsonObject();
for (Map.Entry<String, JsonElement> entry : el.getAsJsonObject().entrySet()) {
obj.add(entry.getKey(), deepClone(entry.getValue()));
}
return obj;
}
throw new IllegalArgumentException("JsonElement type " + el.getClass().getName());
}
And here are a few methods to merge two JsonObject's
public static JsonObject merge(String overrideJson, JsonObject defaultObj) {
return mergeInto((JsonObject)new JsonParser().parse(overrideJson), defaultObj);
}
public static JsonObject merge(JsonObject overrideObj, JsonObject defaultObj) {
return mergeOverride((JsonObject)deepClone(defaultObj), overrideObj);
}
public static JsonObject mergeOverride(JsonObject targetObj, JsonObject overrideObj) {
for (Map.Entry<String, JsonElement> entry : overrideObj.entrySet())
targetObj.add(entry.getKey(), deepClone(entry.getValue()));
return targetObj;
}
public static JsonObject mergeInto(JsonObject targetObj, JsonObject defaultObj) {
for (Map.Entry<String, JsonElement> entry : defaultObj.entrySet()) {
if (targetObj.has(entry.getKey()) == false)
targetObj.add(entry.getKey(), deepClone(entry.getValue()));
}
return targetObj;
}

Categories

Resources