Simple Java Json to Array - java

I'm stuck on something silly I'd appriciate some help with,
I'm getting this string via a stringified object in javascript:
{"63F67024-6FE1-D1B9-41D2-61156F11089A":0,"7cc8732e-d532-463e-9b5e-38fe14664b9e":1,"7CC40FFC-7BED-82DF-41C3-78C2BE8CD901":2,"f7344b33-860a-4934-b1f8-044b80a7b894":3,"31f65628-12b1-4363-848d-2bce07b8ac30":4,"7CF2DCA9-7BEC-8566-41A2-4898E5C110BC":5,"7D1C42ED-7BED-82FE-41D2-5045E9F0C13F":6,"D4EC2E5B-D807-2F30-41EA-6A4D9278BE81":7,"91ACF8F7-9516-F12F-41C1-BF57E6F223BE":8,"28d65730-9da0-457b-9d25-0f33628c0e5c":9,"57D44260-6D6D-E0E0-4171-71080149751C":10}
What's the cleanest, simplest way to convert this into an array of objects?
I've started doing something ugly by just removing the unwanted characters and doing something like this:
List<String> list = new ArrayList<String>(Arrays.asList(value.split(",")));
for(String s : list)
System.out.println(s);
But I'm sure there is a cleaner, simpler way ideally with GSON

Your JSON string looks like a simple list of key/value pairs. How about converting it to a Map
public static void jsonToMap(String t) throws JSONException {
HashMap<String, String> map = new HashMap<String, String>();
JSONObject jObject = new JSONObject(t);
Iterator<?> keys = jObject.keys();
while( keys.hasNext() ){
String key = (String)keys.next();
String value = jObject.getString(key);
map.put(key, value);
}
System.out.println("json : "+jObject);
System.out.println("map : "+map);
}
Hope it helps.

jackson having ObjectMapper class which also doing this but it map the with the object and key name and object field name should be same for mapping code will be
import following package
org.codehaus.jackson.map.ObjectMapper;
call will be
ObjectMapper objectMapper = new ObjectMapper();
Yourclass classObj = objectMapper
.readValue(jsonasString,Yourclass.class);

Related

How to map JSON to Java HashMap

I have a JSON like this: [{key:key1, value:value1}, {key:key2, value:value2}, ..., {key:keyn, value:valuen}]
and I need a HashMap in Java from that json like: {key1:value1, key2:value2, ..., keyn:valuen}
Is there a simple way to have it converted like this? I'm trying with Jackson but don't know how to specify key and value keywords.
It is very simple:
https://stackoverflow.com/a/24012023/7137584
I would recommend using Jackson library:
import com.fasterxml.jackson.databind.ObjectMapper;
TypeReference<HashMap<String, Object>> typeRef = new TypeReference<>() {};
Map<String, Object> mapping = new ObjectMapper().readValue(jsonStr, typeRef);
The input JSON describes an array/list of map entries where each entry is a POJO:
#Data
class Entry {
private String key;
private String value; // the type of value may be Object
}
Here #Data is a Lombok annotation which provides getters, setters, toString, etc.
So, at first a list of map entries is read, which is converted then to the map:
String json = "[{\"key\":\"key1\", \"value\":\"value1\"}, {\"key\":\"key2\", \"value\":\"value2\"}, {\"key\":\"keyN\", \"value\":\"valueN\"}]";
// step 1: read raw list of entries
List<Entry> input = mapper.readValue(json, new TypeReference<List<Entry>>() {});
// step 2: convert to map
Map<String, String> mapRead = input.stream()
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
System.out.println(mapRead);
Output:
{key1=value1, key2=value2, keyN=valueN}
Here's a solution using the JSON-P api.
import javax.json.*;
var str = "[{\"key\":\"key1\", \"value\":\"value1\"}, {\"key\":\"key2\", \"value\":\"value2\"}, {\"key\":\"keyN\", \"value\":\"valueN\"}]";
JsonReader reader = Json.createReader(new StringReader(str));
JsonArray jarr = reader.readArray();
Map<String,String> map = new HashMap<>();
for(JsonValue jv : jarr) {
JsonObject jo = (JsonObject)jv;
map.put(jo.getString("key"), jo.getString("value") );
}
System.out.println(map);
I am using a JsonReader to convert the String to a JsonArray object.
Each entry of this JsonArray is a JsonObject like {key: keyX, value: valueX}.
I get the values corresponding to 'key' and 'value' and add them to a HashMap using a for loop.

Wrong order of data when converting a JTable to JSON [duplicate]

I've a problem trying to make my page printing out the JSONObject in the order i want. In my code, I entered this:
JSONObject myObject = new JSONObject();
myObject.put("userid", "User 1");
myObject.put("amount", "24.23");
myObject.put("success", "NO");
However, when I see the display on my page, it gives:
JSON formatted string: [{"success":"NO", "userid":"User 1", "bid":24.23}]
I need it in the order of userid, amount, then success. Already tried re-ordering in the code, but to no avail. I've also tried .append....need some help here thanks!!
You cannot and should not rely on the ordering of elements within a JSON object.
From the JSON specification at https://www.json.org/
An object is an unordered set of
name/value pairs
As a consequence,
JSON libraries are free to rearrange the order of the elements as they see fit.
This is not a bug.
I agree with the other answers. You cannot rely on the ordering of JSON elements.
However if we need to have an ordered JSON, one solution might be to prepare a LinkedHashMap object with elements and convert it to JSONObject.
#Test
def void testOrdered() {
Map obj = new LinkedHashMap()
obj.put("a", "foo1")
obj.put("b", new Integer(100))
obj.put("c", new Double(1000.21))
obj.put("d", new Boolean(true))
obj.put("e", "foo2")
obj.put("f", "foo3")
obj.put("g", "foo4")
obj.put("h", "foo5")
obj.put("x", null)
JSONObject json = (JSONObject) obj
logger.info("Ordered Json : %s", json.toString())
String expectedJsonString = """{"a":"foo1","b":100,"c":1000.21,"d":true,"e":"foo2","f":"foo3","g":"foo4","h":"foo5"}"""
assertEquals(expectedJsonString, json.toString())
JSONAssert.assertEquals(JSONSerializer.toJSON(expectedJsonString), json)
}
Normally the order is not preserved as below.
#Test
def void testUnordered() {
Map obj = new HashMap()
obj.put("a", "foo1")
obj.put("b", new Integer(100))
obj.put("c", new Double(1000.21))
obj.put("d", new Boolean(true))
obj.put("e", "foo2")
obj.put("f", "foo3")
obj.put("g", "foo4")
obj.put("h", "foo5")
obj.put("x", null)
JSONObject json = (JSONObject) obj
logger.info("Unordered Json : %s", json.toString(3, 3))
String unexpectedJsonString = """{"a":"foo1","b":100,"c":1000.21,"d":true,"e":"foo2","f":"foo3","g":"foo4","h":"foo5"}"""
// string representation of json objects are different
assertFalse(unexpectedJsonString.equals(json.toString()))
// json objects are equal
JSONAssert.assertEquals(JSONSerializer.toJSON(unexpectedJsonString), json)
}
You may check my post too: http://www.flyingtomoon.com/2011/04/preserving-order-in-json.html
u can retain the order, if u use JsonObject that belongs to com.google.gson :D
JsonObject responseObj = new JsonObject();
responseObj.addProperty("userid", "User 1");
responseObj.addProperty("amount", "24.23");
responseObj.addProperty("success", "NO");
Usage of this JsonObject doesn't even bother using Map<>
CHEERS!!!
Real answer can be found in specification, json is unordered.
However as a human reader I ordered my elements in order of importance. Not only is it a more logic way, it happened to be easier to read. Maybe the author of the specification never had to read JSON, I do.. So, Here comes a fix:
/**
* I got really tired of JSON rearranging added properties.
* Specification states:
* "An object is an unordered set of name/value pairs"
* StackOverflow states:
* As a consequence, JSON libraries are free to rearrange the order of the elements as they see fit.
* I state:
* My implementation will freely arrange added properties, IN SEQUENCE ORDER!
* Why did I do it? Cause of readability of created JSON document!
*/
private static class OrderedJSONObjectFactory {
private static Logger log = Logger.getLogger(OrderedJSONObjectFactory.class.getName());
private static boolean setupDone = false;
private static Field JSONObjectMapField = null;
private static void setupFieldAccessor() {
if( !setupDone ) {
setupDone = true;
try {
JSONObjectMapField = JSONObject.class.getDeclaredField("map");
JSONObjectMapField.setAccessible(true);
} catch (NoSuchFieldException ignored) {
log.warning("JSONObject implementation has changed, returning unmodified instance");
}
}
}
private static JSONObject create() {
setupFieldAccessor();
JSONObject result = new JSONObject();
try {
if (JSONObjectMapField != null) {
JSONObjectMapField.set(result, new LinkedHashMap<>());
}
}catch (IllegalAccessException ignored) {}
return result;
}
}
from lemiorhan example
i can solve with just change some line of lemiorhan's code
use:
JSONObject json = new JSONObject(obj);
instead of this:
JSONObject json = (JSONObject) obj
so in my test code is :
Map item_sub2 = new LinkedHashMap();
item_sub2.put("name", "flare");
item_sub2.put("val1", "val1");
item_sub2.put("val2", "val2");
item_sub2.put("size",102);
JSONArray itemarray2 = new JSONArray();
itemarray2.add(item_sub2);
itemarray2.add(item_sub2);//just for test
itemarray2.add(item_sub2);//just for test
Map item_sub1 = new LinkedHashMap();
item_sub1.put("name", "flare");
item_sub1.put("val1", "val1");
item_sub1.put("val2", "val2");
item_sub1.put("children",itemarray2);
JSONArray itemarray = new JSONArray();
itemarray.add(item_sub1);
itemarray.add(item_sub1);//just for test
itemarray.add(item_sub1);//just for test
Map item_root = new LinkedHashMap();
item_root.put("name", "flare");
item_root.put("children",itemarray);
JSONObject json = new JSONObject(item_root);
System.out.println(json.toJSONString());
JavaScript objects, and JSON, have no way to set the order for the keys. You might get it right in Java (I don't know how Java objects work, really) but if it's going to a web client or another consumer of the JSON, there is no guarantee as to the order of keys.
Download "json simple 1.1 jar" from this https://code.google.com/p/json-simple/downloads/detail?name=json_simple-1.1.jar&can=2&q=
And add the jar file to your lib folder
using JSONValue you can convert LinkedHashMap to json string
For those who're using maven, please try com.github.tsohr/json
<!-- https://mvnrepository.com/artifact/com.github.tsohr/json -->
<dependency>
<groupId>com.github.tsohr</groupId>
<artifactId>json</artifactId>
<version>0.0.1</version>
</dependency>
It's forked from JSON-java but switch its map implementation with LinkedHashMap which #lemiorhan noted above.
As all are telling you, JSON does not maintain "sequence" but array does, maybe this could convince you:
Ordered JSONObject
For Java code, Create a POJO class for your object instead of a JSONObject.
and use JSONEncapsulator for your POJO class.
that way order of elements depends on the order of getter setters in your POJO class.
for eg. POJO class will be like
Class myObj{
String userID;
String amount;
String success;
// getter setters in any order that you want
and where you need to send your json object in response
JSONContentEncapsulator<myObj> JSONObject = new JSONEncapsulator<myObj>("myObject");
JSONObject.setObject(myObj);
return Response.status(Status.OK).entity(JSONObject).build();
The response of this line will be
{myObject : {//attributes order same as getter setter order.}}
The main intention here is to send an ordered JSON object as response. We don't need javax.json.JsonObject to achieve that. We could create the ordered json as a string.
First create a LinkedHashMap with all key value pairs in required order. Then generate the json in string as shown below.
Its much easier with Java 8.
public Response getJSONResponse() {
Map<String, String> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("A", "1");
linkedHashMap.put("B", "2");
linkedHashMap.put("C", "3");
String jsonStr = linkedHashMap.entrySet().stream()
.map(x -> "\"" + x.getKey() + "\":\"" + x.getValue() + "\"")
.collect(Collectors.joining(",", "{", "}"));
return Response.ok(jsonStr).build();
}
The response return by this function would be following:
{"A":"1","B":"2","C":"3"}
Underscore-java uses linkedhashmap to store key/value for json. I am the maintainer of the project.
Map<String, Object> myObject = new LinkedHashMap<>();
myObject.put("userid", "User 1");
myObject.put("amount", "24.23");
myObject.put("success", "NO");
System.out.println(U.toJson(myObject));
I found a "neat" reflection tweak on "the interwebs" that I like to share.
(origin: https://towardsdatascience.com/create-an-ordered-jsonobject-in-java-fb9629247d76)
It is about to change underlying collection in org.json.JSONObject to an un-ordering one (LinkedHashMap) by reflection API.
I tested succesfully:
import java.lang.reflect.Field;
import java.util.LinkedHashMap;
import org.json.JSONObject;
private static void makeJSONObjLinear(JSONObject jsonObject) {
try {
Field changeMap = jsonObject.getClass().getDeclaredField("map");
changeMap.setAccessible(true);
changeMap.set(jsonObject, new LinkedHashMap<>());
changeMap.setAccessible(false);
} catch (IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
}
[...]
JSONObject requestBody = new JSONObject();
makeJSONObjLinear(requestBody);
requestBody.put("username", login);
requestBody.put("password", password);
[...]
// returned '{"username": "billy_778", "password": "********"}' == unordered
// instead of '{"password": "********", "username": "billy_778"}' == ordered (by key)
Just add the order with this tag
#JsonPropertyOrder({ "property1", "property2"})
Not sure if I am late to the party but I found this nice example that overrides the JSONObject constructor and makes sure that the JSON data are output in the same way as they are added. Behind the scenes JSONObject uses the MAP and MAP does not guarantee the order hence we need to override it to make sure we are receiving our JSON as per our order.
If you add this to your JSONObject then the resulting JSON would be in the same order as you have created it.
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.LinkedHashMap;
import org.json.JSONObject;
import lombok.extern.java.Log;
#Log
public class JSONOrder {
public static void main(String[] args) throws IOException {
JSONObject jsontest = new JSONObject();
try {
Field changeMap = jsonEvent.getClass().getDeclaredField("map");
changeMap.setAccessible(true);
changeMap.set(jsonEvent, new LinkedHashMap<>());
changeMap.setAccessible(false);
} catch (IllegalAccessException | NoSuchFieldException e) {
log.info(e.getMessage());
}
jsontest.put("one", "I should be first");
jsonEvent.put("two", "I should be second");
jsonEvent.put("third", "I should be third");
System.out.println(jsonEvent);
}
}
Just use LinkedHashMap to keep de order and transform it to json with jackson
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.LinkedHashMap;
LinkedHashMap<String, Object> obj = new LinkedHashMap<String, Object>();
stats.put("aaa", "aaa");
stats.put("bbb", "bbb");
stats.put("ccc", "ccc");
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
System.out.println(json);
maven dependency
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.10.7</version>
</dependency>
I just want the order for android unit tests that are somehow randomly changing overtime with this cool org.json.JSONObject, even thou it looks like it uses linked map but probably depends on api you compile it with or something, so it has different impl. with different android api probably.
I would suggest something like this:
object Json {
#SuppressLint("DiscouragedPrivateApi")
fun Object() = org.json.JSONObject().apply {
runCatching {
val nameValuePairs: Field = javaClass.getDeclaredField("nameValuePairs")
nameValuePairs.isAccessible = true
nameValuePairs.set(this, LinkedHashMap<String, Any?>())
}.onFailure { it.printStackTrace() }
}
}
Usage:
val jsonObject = Json.Object()
...
This is just some possibility I use it little differently so I modified it to post here. Sure gson or other lib is another option.
Suggestions that specification is bla bla are so shortsighted here, why you guys even post it, who cares about 15 years old json spec, everyone wants it ordered anyway.

Remove duplicate key and value from json in java

I am mapping Object (i don't have control over) to jsonString, after mapping I get duplicate key-value pairs in the JSON,
example
{
"id":"123",
"email":"someEmail#gmail.com",
"UserName":"someOne",
"EMAIL":"someEmail#gmail.com"
}
the duplicate is exactly the same except that it is in uppercase letters.
I am trying to get a jsonInString format without the duplication. Something like this:
{
"id":"123",
"email":"someEmail#gmail.com",
"UserName":"someOne"
}
I have tried
String jsonInStringWithOutDuplication=mapper.enable(
JsonParser.Feature.STRICT_DUPLICATE_DETECTION).writeValueAsString(users);
with no luck, any suggestions?
If you don't find a way to configure the ObjectMapper to filter out duplicate attributes, you can serialize the problematic object to JSON, then serialize the JSON to a Map object, merge duplicate attributes and serialize it to JSON again:
Map<String, String> objectWithDuplicates = new HashMap<>();
map.put("name", "MyName");
map.put("email", "em#ail");
map.put("EMAIL", "em#ail");
ObjectMapper mapper = new ObjectMapper();
String jsonWithDuplicates = mapper.writeValueAsString(objectWithDuplicates);
Map<String, Object> attributesWithDuplicates = mapper
.readValue(jsonWithDuplicates, Map.class);
Map<String, Object> withoutDuplicates = new HashMap<>();
attributesWithDuplicates.forEach((key, value) -> {
if (! withoutDuplicates.containsKey(key.toLowerCase())) {
withoutDuplicates.put(key.toLowerCase(), value);
}
});
String json = mapper.writeValueAsString(withoutDuplicates);
Jackson's ObjectMapper has a feature that puts the same keys into an array. Isn't it something that could help you?
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new GuavaModule());
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
Multimap resultAsMultimap = mapper.readValue(json, Multimap.class);
System.out.println(resultAsMultimap);

toString() changes the curly braces into square?

I have the following construct in my code for the following JSON
SomeVariable =
{
"FirstVar":{
"service1":"value1"
}
}
For this I have the following
code in Java
Map<String,String> internal_service_var = new HashMap<String,String>();
internal_service_endpoint.put("service1","value1");
Map<String, String> first_var = new HashMap<String,String>();
first_var.put("FirstVar", internal_service_var.entrySet().toString());
Map<String, String> some_var = new HashMap<String, String>();
some_var.put("SomeVariable", first_var.entrySet().toString());
Here is how I try to use it in the JSON to send over wire
Note that the value of the property in the JSON needs to be a String
JSONObject json = new JSONObject
json.put("var", some_var);
This sets the 'var' property in the json to be
[SomeVariable = [ "FirstVar":[ "service1":"value1"]]]
Instead of
SomeVariable = { "FirstVar":{ "service1":"value1"}}
What am I missing?
The toString() of HashMap does not return the data in JSON format. If you want JSON objects use only JSONObject.
Alternatively, use xstream:
XStream xstream = new XStream(new JettisonMappedXmlDriver());
xstream.setMode(XStream.NO_REFERENCES);
String jsonRepresentation = map.toXML();
jsonRepresentation will have your json. Yes, for reasons only known to ancient sages, xstream uses toXML for serialization. It's misnamed, and unlikely to change to anything else.

Convert JSONObject to Map

I have a JSONObject with some attributes that I want to convert into a Map<String, Object>
Is there something that I can use from the json.org or ObjectMapper?
You can use Gson() (com.google.gson) library if you find any difficulty using Jackson.
//changed yourJsonObject.toString() to yourJsonObject as suggested by Martin Meeser
HashMap<String, Object> yourHashMap = new Gson().fromJson(yourJsonObject, HashMap.class);
use Jackson (https://github.com/FasterXML/jackson) from http://json.org/
HashMap<String,Object> result =
new ObjectMapper().readValue(<JSON_OBJECT>, HashMap.class);
This is what worked for me:
public static Map<String, Object> toMap(JSONObject jsonobj) throws JSONException {
Map<String, Object> map = new HashMap<String, Object>();
Iterator<String> keys = jsonobj.keys();
while(keys.hasNext()) {
String key = keys.next();
Object value = jsonobj.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;
}
Most of this is from this question: How to convert JSONObject to new Map for all its keys using iterator java
The best way to convert it to HashMap<String, Object> is this:
HashMap<String, Object> result = new ObjectMapper().readValue(jsonString, new TypeReference<Map<String, Object>>(){}));
Note to the above solution (from A Paul):
The solution doesn't work, cause it doesn't reconstructs back a HashMap< String, Object > - instead it creates a HashMap< String, LinkedHashMap >.
Reason why is because during demarshalling, each Object (JSON marshalled as a LinkedHashMap) is used as-is, it takes 1-on-1 the LinkedHashMap (instead of converting the LinkedHashMap back to its proper Object).
If you had a HashMap< String, MyOwnObject > then proper demarshalling was possible - see following example:
ObjectMapper mapper = new ObjectMapper();
TypeFactory typeFactory = mapper.getTypeFactory();
MapType mapType = typeFactory.constructMapType(HashMap.class, String.class, MyOwnObject.class);
HashMap<String, MyOwnObject> map = mapper.readValue(new StringReader(hashTable.toString()), mapType);
The JSONObject has a method toMap which returns Map<String,Object>.
The Maven dependency used in pom.xml:
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>current-version</version>
</dependency>
You can find the current-version here.
Found out these problems can be addressed by using
ObjectMapper#convertValue(Object fromValue, Class<T> toValueType)
As a result, the origal quuestion can be solved in a 2-step converison:
Demarshall the JSON back to an object - in which the Map<String, Object> is demarshalled as a HashMap<String, LinkedHashMap>, by using bjectMapper#readValue().
Convert inner LinkedHashMaps back to proper objects
ObjectMapper mapper = new ObjectMapper();
Class clazz = (Class) Class.forName(classType);
MyOwnObject value = mapper.convertValue(value, clazz);
To prevent the 'classType' has to be known in advance, I enforced during marshalling an extra Map was added, containing <key, classNameString> pairs. So at unmarshalling time, the classType can be extracted dynamically.
This is how I did it in Kotlin:
mutableMapOf<String, Any>().apply {
jsonObj.keys().forEach { put(it, jsonObj[it]) }
}
import com.alibaba.fastjson.JSONObject;
Map<String, Object> map = new HashMap<String, Object>();
JSONObject rec = JSONObject.parseObject(<JSONString>);
map.put(rec.get("code").toString(), rec.get("value").toString());

Categories

Resources