I have a JsonObject e.g
JsonObject jsonObject = {"keyInt":2,"keyString":"val1","id":"0123456"}
Every JsonObject contains a "id" entry, but the number of other key/value pairs is NOT determined, so I want to create create an object with 2 attributes:
class myGenericObject {
Map<String, Object> attributes;
String id;
}
So I want my attributes map to look like this:
"keyInt" -> 4711
"keyStr" -> "val1"
I found this solution
Map<String, Object> attributes = new HashMap<String, Object>();
Set<Entry<String, JsonElement>> entrySet = jsonObject.entrySet();
for(Map.Entry<String,JsonElement> entry : entrySet){
attributes.put(entry.getKey(), jsonObject.get(entry.getKey()));
}
but the values are enclosed by ""
"keyInt" -> "4711"
"keyStr" -> ""val1""
How to get the plain values (4711 and "val1")?
Input data:
{
"id": 0815,
"a": "a string",
"b": 123.4,
"c": {
"a": 1,
"b": true,
"c": ["a", "b", "c"]
}
}
or
{
"id": 4711,
"x": false,
"y": "y?",
}
replace "" with blank.
Map<String, Object> attributes = new HashMap<String, Object>();
Set<Entry<String, JsonElement>> entrySet = jsonObject.entrySet();
for(Map.Entry<String,JsonElement> entry : entrySet){
if (! nonProperties.contains(entry.getKey())) {
properties.put(entry.getKey(), jsonObject.get(entry.getKey()).replace("\"",""));
}
}
How are you creating your JsonObject? Your code works for me. Consider this
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
...
...
...
try{
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("keyInt", 2);
jsonObject.addProperty("keyString", "val1");
jsonObject.addProperty("id", "0123456");
System.out.println("json >>> "+jsonObject);
Map<String, Object> attributes = new HashMap<String, Object>();
Set<Entry<String, JsonElement>> entrySet = jsonObject.entrySet();
for(Map.Entry<String,JsonElement> entry : entrySet){
attributes.put(entry.getKey(), jsonObject.get(entry.getKey()));
}
for(Map.Entry<String,Object> att : attributes.entrySet()){
System.out.println("key >>> "+att.getKey());
System.out.println("val >>> "+att.getValue());
}
}
catch (Exception ex){
System.out.println(ex);
}
And it is working fine. Now I am interested in knowing how you created that JSON of yours?
You can also try this (JSONObject)
import org.json.JSONObject;
...
...
...
try{
JSONObject jsonObject = new JSONObject("{\"keyInt\":2,\"keyString\":\"val1\",\"id\":\"0123456\"}");
System.out.println("JSON :: "+jsonObject.toString());
Iterator<String> it = jsonObject.keys();
while( it.hasNext() ){
String key = it.next();
System.out.println("Key:: !!! >>> "+key);
Object value = jsonObject.get(key);
System.out.println("Value Type "+value.getClass().getName());
}
}
catch (Exception ex){
System.out.println(ex);
}
Just make following changes...
Map<String, Object> attributes = new HashMap<String, Object>();
Set<Entry<String, JsonElement>> entrySet = jsonObject.entrySet();
for(Map.Entry<String,JsonElement> entry : entrySet){
attributes.put(entry.getKey(), jsonObject.get(entry.getKey()).getAsString());
}
"getAsString" will do the magic for u
Your Map values are JsonElements. Whenever you print a JsonElement (e.g. using a debugger) its toString() method will be called - and since a JsonElement has many implementing classes the default toString implementation wraps the value in quotes to ensure correct JSON. To get the value as a normal, unwrapped String, simply call getAsString():
JsonElement elem;
// ...
String value = elem.getAsString();
With your example:
Map<String, Object> attributes = new HashMap<String, Object>();
Set<Entry<String, JsonElement>> entrySet = jsonObject.entrySet();
for(Map.Entry<String,JsonElement> entry : entrySet){
attributes.put(entry.getKey(), jsonObject.get(entry.getKey()).getAsString());
}
Note there are many other methods you can call on a JsonElement to produce other types.
I am not quite sure why you want to do manual manipulation in the first place. GSON decode will simply leave those absent key/value pairs as default value (zero,null). And then you can process as you want.
Related
I have a Json String representing a object which further has another nested objects. Also, I have a list of keys which I need to remove from this Json String. These keys can be at any nested level of object inside this string. Finally I need to compare this edited Json string to another string and output the differences. I need to remove those key-value pairs from first Json string because I need to ignore those keys during comparison. Currently, I am converting the Json String to LinkedTreeMap provided by Gson API and then doing Map.difference() to compare. Please suggest a solution to this.
I did it by traversing recursively inside the Nested LinkedTreeMap till I find the field and remove it if it exists. The full path of Key needs to be provide to get the exact key-value location inside the Object (like "objects.desc" in the below Json Sample to remove desc from the Json String)
Json Sample:
{
"message": "MSG",
"code": "COD001",
"objects": [
{
"resource": "Student",
"field": "StudentId",
"desc": "Student Description"
}
]
}
Code Sample:
public MapDifference<String, Object> getMapDifference(String jsonString1, String jsonString2) {
MapDifference<String, Object> mapDifference = null;
Gson gson = new Gson();
Type mapType = new TypeToken<Map<String, Object>>() {
}.getType();
Map<String, Object> firstMap = gson.fromJson(jsonString1, mapType);
Map<String, Object> secondMap = gson.fromJson(jsonString2, mapType);
firstMap = CollectionUtils.isEmpty(firstMap) ? new HashMap<>() : firstMap;
secondMap = CollectionUtils.isEmpty(secondMap) ? new HashMap<>() : secondMap;
//This contains the List of keys that is required to be filtered out from Json Strings before comparision like {"message", "objects.desc"}
List<String> firstIgnoreList = getIgnoreList1();
List<String> secondIgnoreList = getIgnoreList2();
filterKeys(firstMap, firstIgnoreList);
filterKeys(secondMap, secondIgnoreList);
mapDifference = Maps.difference(firstMap, secondMap);
return mapDifference;
}
private void filterKeys(Map<String, Object> keyMap, List<String> ignoreList) {
if (!(CollectionUtils.isEmpty(keyMap) || CollectionUtils.isEmpty(ignoreList))) {
ignoreList.stream().parallel().forEach(key -> recursiveRemove(keyMap, key));
}
}
private static void recursiveRemove(Map<String, Object> keyMap, String key) {
List<String> path = Arrays.asList(StringUtils.split(key.trim(), "."));
int size = path.size();
int index = 0;
List<LinkedTreeMap> treeMapList = new ArrayList<LinkedTreeMap>();
treeMapList.add((LinkedTreeMap) keyMap);
while (index != size - 1) {
int i = index++;
List<LinkedTreeMap> treeMapListTemp = new ArrayList<LinkedTreeMap>();
treeMapList.stream().parallel().forEach(treeMap -> {
Object obj = treeMap.get(path.get(i));
if (obj instanceof List) {
treeMapListTemp.addAll((List<LinkedTreeMap>) obj);
} else if (obj instanceof LinkedTreeMap) {
treeMapListTemp.add((LinkedTreeMap) obj);
}
});
treeMapList = treeMapListTemp;
}
treeMapList.stream().parallel().forEach(treeMap -> treeMap.remove(path.get(size - 1)));
}
I'm trying to create complex JSon output file with some data(HashTable collections in one big) and got some error on serializing the output. After some investigation found that need to set Visibility to these property fields and now i see strange values for HastTable in my output, that actually i don't need them. Here is some code:
PrintWriter out = null;
Map<String, String> hm = new HashMap<String, String>();
Map<String, String> hmReqMap = new HashMap<String, String>();
Map<String, String> hmResMap = new HashMap<String, String>();
Map<String, String> hmGate = new HashMap<String, String>();
Map<String, String> hmResult = new HashMap<String, String>();
JSONArray ja = new JSONArray();
JSONObject mainObj = new JSONObject();
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
try {
File file = new File(outputDirectory + File.separator + "aaa" + IConst.JSON_EXTENSION);
out = new PrintWriter(new BufferedWriter(new FileWriter(file, true)));
if (tcStats != null) {
for (SingleTest singleTest : tcStats.getTestsList()) {
Map<String, String> reqMap = new HashMap<String, String>();
Map<String, String> resMap = new HashMap<String, String>();
SomeClassAllDetails allDdetails = singleTest.getSiteTransaction();
for (Entry<String, String> entry : allDetails.getEPowerEntries().entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (key.startsWith("req.")) {
reqMap.put(key.substring(4), value);
} else if (key.startsWith("res.")) {
resMap.put(key.substring(4), value);
}
}
hmGate.put("Gate", singleTest.getGate().toString());
hmReqMap.put("Request", reqMap.toString().substring(1, reqMap.toString().length() - 1));
hmResMap.put("Response", resMap.toString().substring(1, resMap.toString().length() - 1));
hmResult.put("Result", singleTest.getComparisonResult().toString());
hm.putAll(hmGate);
hm.putAll(hmReqMap);
hm.putAll(hmResMap);
hm.putAll(hmResult);
ja.put(hm);
mainObj.put(singleTest.getLabel(), ja);
}
String mapAsJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(mainObj);
out.println(mapAsJson);
out.println(",");
} else if ("opening".equals(type)) {
out.println("{");
} else if ("closing".equals(type)) {
out.println("}");
}
That's the actually output and as you can see the keys like map,myArrayList are added here:
{
"map" : {
"Tran_ID" : {
"myArrayList" : [ {
"map" : {
"Response" : "value1=333333 value2=33333, value4=5555",
"Request" : "value6=44444, value7=000000",
"Gate" : "10.0.0.1",
"Result" : "Done"
}
} ]
}
}
}
How do i remove them?
If i remove the following code
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
then i got error that i need to disable SerializationFeature.FAIL_ON_EMPTY_BEANS
My goal is to create this Json Output:
{
"Tran_ID" : [{
"Response" : "value1=333333 value2=33333, value4=5555",
"Request" : "value6=44444, value7=000000",
"Gate" : "10.0.0.1",
"Result" : "Done"
}]
}
OK, here is a solution:
Go to http://www.jsonschema2pojo.org/ (NB: I'm not affiliated with this site, it's just a handy tool)
Select "Source type": "JSON" and you correct jackson version below. Also uncheck "Allow additional properties" (on the the right)
Copy/paste your wanted JSON on the left big text box.
Clic on preview at the bottom, this will generates your java classes.
Next step is to "fill" a class instance with your data
Sample "filling" code (with generated classes name):
TranID tranId = new TranID(); // {}
tranId.setResponse("value1=333333, value2=33333, value4=5555"); // { "Response": ... }
tranId.setRequest("value6=44444, value7=000000"); // { "Response": ..., "Request": ... }
tranId.setGate("10.0.0.1"); // etc
tranId.setResult("Done")
Example example = new Example(); // { "tranID": undefined }
example.setTranId(new ArrayList<>()); // { "tranID": [] }
example.getTranId().add(tranId); // { "tranID": [{ "Response": ..., "Request": ... }] }
// output
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(example);
Thanks for your help, but it didn't really help to problem
and I rewrote the code and put this one:
String jo = Json.createObjectBuilder()
.add(singleTest.getLabel(), Json.createObjectBuilder()
.add("Request", reqMap.toString().substring(1, reqMap.toString().length() - 1))
.add("Response", resMap.toString().substring(1, resMap.toString().length() - 1))
.add("Result", singleTest.getComparisonResult().toString())
.add("Gate", singleTest.getGate().toString()))
.build().toString();
You should also add to pom.xml these dependencies:
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.4</version>
<dependency>
<groupId>javax.json</groupId>
<artifactId>javax.json-api</artifactId>
<version>1.0</version>
And then you can do whatever you want with you string.
Thanks
I'm getting JSON, but it's not in alphabetical order. How to sort json by it's KEY ?
JSON:
{"b":"3","c":"1","a":"4"}
Expected output:
{"a":"4","b":"3","c":"1"}
Please help me to solve this problem. I really appreciate your help! Thanks!
You can use the jackson library.
First add a jackson to the maven dependency.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.7</version>
</dependency>
Then use the code below.
String jsonData = "{\"e\":\"6\",\"f\":\"1\",\"b\":\"3\",\"c\":\"1\",\"a\":\"4\"}";
ObjectMapper om = new ObjectMapper();
om.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
Map<String, Object> map = om.readValue(jsonData, HashMap.class);
String json = om.writeValueAsString(map);
System.out.println(json); // result : {"a":"4","b":"3","c":"1","e":"6","f":"1"}
When I test it, I get output in sorted form.
{"a":"4","b":"3","c":"1","e":"6","f":"1"}
So here is one of solution to sort JSON object by key alphabetically without using external libraries(for Android Studio). The sortedJSON is the one with key sorted alphabetically.
try{
JSONObject jo = new JSONObject();
jo.put("g", "9");
jo.put("t", "8");
jo.put("r", "7");
jo.put("d", "6");
jo.put("c", "5");
jo.put("b", "4");
jo.put("a", "1");
Map<String, String> joToMap = new HashMap<>();
Iterator<String> keysItr = jo.keys();
while (keysItr.hasNext()) {
String key = keysItr.next();
Object value = jo.get(key);
joToMap.put(key, value.toString()); //since value is string so convert toString; depend on your value type
}
Map<String, String> sortedMap = new TreeMap<>(joToMap); //this will auto-sort by key alphabetically
JSONObject sortedJSON = new JSONObject(); //recreate new JSON object for sorted result
for (Map.Entry<String, String> entry : sortedMap.entrySet()) {
sortedJSON.put(entry.getKey(), entry.getValue());
// result will be {"a":"1","b":"4","c":"5","d":"6","g":"9","r":"7","t":"8"}
}
} catch (Exception e){
}
You can use maps for this purpose , then sort the map according to the map key. after that insert it into the JSON object.
In your case declare the map as:
Map<String,Integer> mapName = new HashMap<>();
can map be compare with arraylist of string in java
private Map<String, String> checkInScopeLobs(Map<String, String> allLobsChkBx)
{
Map<String, String> inScopeLobs = new HashMap<String, String>();;
for (Map.Entry<String, String> entry : allLobsChkBx.entrySet())
{
if(entry.getKey().contains("1") || entry.getKey().contains("2") || entry.getKey().contains("3")){
inScopeLobs.put(entry.getKey(), entry.getValue());
}
}
return inScopeLobs;
}
is this a correct way ?
You can make use of keySet(). This method returns a Set of keys (for more info, Docs from Oracle about Map). This means less overhead than iterating over your whole map. In the following case you'll only request values of matching keys.
There are some other faults like a double semicolon and since JDK7 you don't have to define your map when initializing.
private Map<String, String> checkInScopeLobs(Map<String, String> allLobsChkBx) {
Map<String, String> inScopeLobs = new HashMap();
List<String> keys = Arrays.asList( { "1", "2", "3" } );
for(String key : allLobsChkBx.keySet()) {
if(keys.contains(key)) {
inScopeLobs.put(key, allLobsChkBx.get(key));
}
}
return inScopeLobs;
}
Why aren't you using an Integer instead of a String, since you're only storing numbers.
Since key is String you can use matches method from String class
for (Map.Entry<String, String> entry : allLobsChkBx.entrySet())
{
if(entry.getKey().matches(".*[123].*")){
inScopeLobs.put(entry.getKey(), entry.getValue());
}
}
Actually there are no such methods, but you can try this approach:
Map<String, String> allLobsChkBx = new HashMap<String, String>(4);
allLobsChkBx.put("1", "A");
allLobsChkBx.put("2", "B");
allLobsChkBx.put("3", "C");
allLobsChkBx.put("4", "D");
allLobsChkBx.put("5", "E");
System.out.println("Before retain: " + allLobsChkBx);
List<String> keysToRetain = Arrays.asList(new String[] { "1", "2", "3" });
allLobsChkBx.keySet().retainAll(keysToRetain);
System.out.println("After retain: " + allLobsChkBx);
It will produce following output:
Before retain: {3=C, 2=B, 1=A, 5=E, 4=D}
After retain: {3=C, 2=B, 1=A}
I'm using the following code to get JSON data from file, currently I was able to achieve the JSON but in one string. I want to parse it to array. The json file is like this:
{
"employee": [
{
"name": "joan",
"lastname": "test",
"age": 23
},
I'm using the following code to get the data but I get it in one string and I want to print some of the data
JSONObject jsonObject = (JSONObject) parser
.parse(new FileReader("C:\\MockData\\Json\\js.txt"));
JSONParser parser1 = new JSONParser();
ContainerFactory containerFactory = new ContainerFactory() {
public List<?> creatArrayContainer() {
return new LinkedList<Object>();
}
public Map<?, ?> createObjectContainer() {
return new LinkedHashMap<Object, Object>();
}
};
Map<?, ?> json = (Map<?, ?>) parser1.parse(jsonObject.toJSONString(), containerFactory);
Iterator<?> iter = json.entrySet().iterator();
System.out.println("==iterate result==");
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
System.out.println(entry.getKey() + "=>" + entry.getValue());
}
this is the output
employee=[{age=23, name=joan, lastname=test}, {age=22, name=Alex, lastname=avz}, {age=65, name=Dan, lastname=severn}]
Here the entry.getValue() is retuen one concatenated string of the array,
the while is running just one time...
but I want to loop on it to take the key value. How should I do that?
for example if I want to print name alex witn age 22 how should I do that?
Note: The file can be changed so I don't know the keys (now its name but in can be firstName and any other field for that i need generic solution).
if there is a way to use different parser that can do that Im open.
The following is the full solution to your question.
With this code you can break down the data to each employee and also separate the employee attributes.
Set<String> keySet = jsonObject.keySet();
Iterator keySetIterator = keySet.iterator();
while(keySetIterator.hasNext()){
JSONArray array = (JSONArray)jsonObject.get(keySetIterator.next());
while(employeeKeySetIterator.hasNext()){
String employeeKey = employeeKeySetIterator.next().toString();
System.out.println(employeeKey + " : "+ employee.get(employeeKey));
}
}
}
You need to cast the inner json string to a JSONArray
JSONArray array = (JSONArray)jsonObject.get("employee");
Iterator<JSONObject> iterator = array.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next().toString());
}