Java json object replace keys names - java

I have Json like this:
{
"_id" : ObjectId("5e99f6d16cbddf7dad26557f"),
"channel_id" : 49066,
"timestamp" : NumberLong(1580982302003),
"values" : {
"some id" : "81151501",
"some title" : "Some title",
"some address" : "https://www.some-address.com",
"new hash" : {
"some value" : "5",
"other value" : " 54.10 BRL"
},
"wrong values" : "This text have wrong & values & and netx is wrong too & and this &"
},
"null value" : null,
"zero integer" : 0
}
I need to loop through each key and replace spaces with snake_case, for example from other value to other_value
Additionally, I wanted to check every value in the loop by replacing the character & with _, for example:
from This text have wrong & values & and netx is wrong too & and this & to This text have wrong _ values _ and netx is wrong too _ and this _
My json object is made from:
JSONobject jsonObject = new JSONobject(jsonString)

You could iterate over the keys, normalize the key and recursively continue as long as the value is a JSONObject. If it's not, then you could normalize the value as well. So this would look something like this:
static JSONObject normalize(JSONObject object) throws JSONException {
JSONObject result = new JSONObject();
Iterator iterator = object.keys();
while (iterator.hasNext()) {
String key = (String) iterator.next();
String normalizedKey = key.replace(" ", "_");
Object inner = object.get(key);
if (inner instanceof JSONObject) {
result.put(normalizedKey, normalize((JSONObject) inner));
} else if (inner instanceof String) {
result.put(normalizedKey, object.getString(key).replace("&", "_"));
} else {
result.put(normalizedKey, inner);
}
}
return result;
}
Latest version of the library also provides the ability to obtain a keyset, which would allow for a slightly cleaner looping of the keys:
static JSONObject normalized(JSONObject object) {
JSONObject result = new JSONObject();
object.keySet().forEach(key -> {
String normalizedKey = key.replace(" ", "_");
Object value = object.get(key);
if (value instanceof JSONObject) {
result.put(normalizedKey, normalized((JSONObject) value));
} else if (value instanceof String) {
result.put(normalizedKey, ((String) value).replace("&", "_"));
} else {
result.put(normalizedKey, value);
}
});
return result;
}

Related

How would one convert a JSONObject into a DefaultMutableTreeNode in java?

I want to create a way to convert a JSONObject like this:
"master root" : {
"folder 1" : {
"folder 2" : {
"example data" : "some more example values",
"example data" : "some more examples"
},
"example data" : "example value"
},
"example data" : "lol"
}
to something like this:
example tree image
I have tried a method that looks something like this:
public javax.swing.tree.DefaultMutableTreeNode createSingleTreeNode(JSONObject obj) {
for(Iterator iterator = obj.keySet().iterator(); iterator.hasNext();) {
String key = (String) iterator.next();
if (obj.get(key) instanceof JSONObject) {
javax.swing.tree.DefaultMutableTreeNode node1 = new javax.swing.tree.DefaultMutableTreeNode(key);
node1.add(createSingleTreeNode((JSONObject) obj.get(key)));
return node1;
} else {
return new javax.swing.tree.DefaultMutableTreeNode(key);
}
}
return new javax.swing.tree.DefaultMutableTreeNode("");
}
It works to some degree but stops after it gets to the first item that isn't a json object it just stops and only adds one.
Any ideas on how to do this properly? (I'm new to java so i'm sorry if there is a library that does this already)
I fixed it, instead of returning the node, it will add the node to the "master" node that you add as a parameter, here is the code
public void createSingleTreeNode(JSONObject obj, javax.swing.tree.DefaultMutableTreeNode master) {
javax.swing.tree.DefaultMutableTreeNode[] nodes = {};
for(Iterator iterator = obj.keySet().iterator(); iterator.hasNext();) {
String key = (String) iterator.next();
if (obj.get(key) instanceof JSONObject) {
javax.swing.tree.DefaultMutableTreeNode node1 = new javax.swing.tree.DefaultMutableTreeNode(key);
LT.createSingleTreeNode((JSONObject) obj.get(key), node1);
master.add(node1);
} else {
nodes = Arrays.copyOf(nodes, nodes.length + 1);
nodes[nodes.length - 1] = new javax.swing.tree.DefaultMutableTreeNode(key);
}
}
for (DefaultMutableTreeNode node : nodes) {
master.add(node);
}
}

JSONObject from dot seperated strings

I am struggling with a specific problem, that I cannot think of correctly. The following is the problem
I have a map with key value like the following, i just used strings here
String key = "activate.message.success"
String value = "success"
String key1 = "activate.title"
String value1 = "Good Title"
String key2 = "activate.message.error"
String value2 = "error"
String key3 = "activate.message.short.poll"
String value3 = "This is short poll"
I need to build a json like the following
{
"activate":{
"message":{
"success":"success",
"error":"error",
"short":{
"poll":"This is short poll"
}
},
"title":"Good Title"
}
}
I could not think of a proper solution for this use case and struggling for 3 hours. I thought of using recursion, but i dont how exactly i could do. Please help with this. I am using java for this, I should use generic JSONObject to solve as there is not POJO mappings. So far I have just splitted the strings using separtor and stored in an another map like the following
public Map<String, Object> getJsonObjectFromKeyValueMap(Map<String, String> stringValueMap,
Map<String, Object> stringObjectMap) {
for (Entry entry : stringValueMap.entrySet()) {
String[] keyValueArrayString = entry.getKey().toString().split("\\.");
int sizeOfMap = keyValueArrayString.length;
int i = 0;
String concatString = "";
for (String processKey : keyValueArrayString) {
if (i < sizeOfMap - 1) {
concatString += processKey + ".";
stringObjectMap.put(concatString, (Object) new JSONObject());
} else {
concatString += processKey;
stringObjectMap.put(concatString, entry.getValue());
concatString = "";
}
i++;
}
}
return stringObjectMap;
}
First, let's update your data into a proper map :
Map<String, String> data = new HashMap<>();
data.put("activate.message.success", "success");
data.put("activate.title", "Good Title");
data.put("activate.message.error", "error");
data.put("activate.message.short.poll", "This is short poll");
Then, your logic is pretty close, for each node but the last, you create a new JSONObject, for the last, you insert the value.
If you try to build a JSONObject instead of the map directly, you would get a pretty good result already, well somewhat of a result.
The following will iterate a Map<String, String> of data.
For each entry, we split the key to getting the nodes.
Then, we just need to move in the json, if a node doesn't exist, we create it.
Then, for the last value, create the value.
public static JSONObject build(Map<String, String> data) {
JSONObject json = new JSONObject();
//Iterate the map entries
for (Entry<String, String> e : data.entrySet()) {
String[] keys = e.getKey().split("\\.");
// start from the root
JSONObject current = json;
for (int i = 0; i < keys.length; ++i) {
String key = keys[i];
//Search for the current node
try {
//If it exist, do nothing
current = current.getJSONObject(key);
} //If it does not exist
catch (JSONException ex) {
//Is it the last node, create the value
if (i == keys.length - 1) {
current.put(key, e.getValue());
} //Not the last node, create a new JSONObject
else {
JSONObject tmp = new JSONObject();
current.put(key, tmp);
current = tmp; //Always replace current with the last node to go deeped each iteration
}
}
}
}
return json;
}
And the example :
public static void main(String[] args) {
Map<String, String> data = new HashMap<>();
data.put("activate.message.success", "success");
data.put("activate.title", "Good Title");
data.put("activate.message.error", "error");
data.put("activate.message.short.poll", "This is short poll");
JSONObject json = build(data);
System.out.println(json.toString(4));
}
Ouptut:
{"activate": {
"message": {
"success": "success",
"short": {"poll": "This is short poll"},
"error": "error"
},
"title": "Good Title"
}}
Note : I used an exception to check for the existance of the key, if the map is huge, this could have some impact so you can simply use :
if(current.isNull(key)){
if (i == keys.length - 1) {
current.put(key, e.getValue());
} else {
JSONObject tmp = new JSONObject();
current.put(key, tmp);
current = tmp;
}
} else {
current = current.getJSONObject(key);
}
This was created using org.json/json

How correctly iterate json in java?

I'm trying to write a cordova plugin.
I've the following JSON data:
JSONObject obj = {"amount":100, "desc":"blabla",id:123}
and I'm trying to iterate the JSON keys and put keys and values to intent.putExtra(key,val)
Example:
Iterator<String> iter = obj.keys();
while (iter.hasNext()) {
key = iter.next();
value = obj.getString(key);
intent.putExtra(key, value);
}
With this code I get the error
error: cannot find symbol intent.putExtra(key, value);
Anyone can say me how correct iterate JSON data and execute putExtra()?
First, the json you provide is not valid. It should be something like:
{"amount":100, "desc":"blabla","id":123}
Then, as said in the comments, create an intent variable outside the for loop.
And finally, you should use
Object value = obj.get(key)
because values can be Strings or Integers.
Extension to Lino's answer.
As Intent.putExtra(String, Object) is not available, you need following modifications.
JSONObject obj = new JSONObject("{" +
"\"amount\": 100," +
"\"desc\": \"blabla\"," +
"\"id\": 123," +
"\"id2\": 123.56" +
"}");
Intent intent = new Intent();
Iterator<String> iter = obj.keys();
while (iter.hasNext()) {
String key = iter.next();
Object value = obj.get(key);
if (value instanceof Float || value instanceof Double) {
intent.putExtra(key, (double) value);
} else if (value instanceof Integer || value instanceof Long) {
intent.putExtra(key, (long) value);
} else if (value instanceof String) {
intent.putExtra(key, (String) value);
} /*else if (more cases go here) {
} */
}

Retrieve name of fields of a JSONObject - Java

I have to retrieve all name of fields of JSONObjectin Java.
For example, this is a JSON:
{
"name" : {
"first" : "John",
"last" : "McCarthy"
},
"birth" : ISODate("1927-09-04T04:00:00.000Z"),
"death" : ISODate("2011-12-24T05:00:00.000Z"),
"contribs" : [
"Lisp",
"Artificial Intelligence",
"ALGOL"
]
}
This JSON object is just an example, I can't know what a JSONObject contains since I import it. I don't have any information about the name of fields to use Gson/Jackson to deserialization.
Suppose I have a JSONObject myDocJson that contains the previous JSON Object, I use an iterator:
Iterator<?> keys = myDocJson.keySet().iterator();
while(keys.hasNext()) {
System.out.println(keys.next());
}
And as a result I get:
name
birth
death
contribs
But for example I don't have name.first and name.last. So this iterator does not work with innested Object.
You are only printing the keys.
To get the values, try
JSONObject object = null; // your json object
for (Object key : object.keySet()) {
System.out.println(key + "=" + object.get(key)); // to get the value
}
EDIT
And for the objects inside of your JSONObject try
JSONObject object = null; // your json object
for (Object key : object.keySet()) {
System.out.println(key + "=" + object.get(key)); // to get the value
for (Object subKey : ((JSONObject) object.get(key)).keySet()) {
System.out.println(subKey + "=" + object.get(subKey));
}
}

How to properly uplevel a json key in java? Why is the json not changing?

I have an array "myarray" like this:
[{
name: John,
age: {
years:18
},
computer_skills: {
years:4
},
mile_runner: {
years:2
}
}]
How do I uplevel it properly? Using minimal-json, I do the following:
JsonArray jsonArray = JsonArray.readFrom(myarray);
for( JsonValue val : jsonArray) {
JsonObject myObj = val.asObject();
for( JsonObject.Member myMember : myObj ) {
if(myMember.getValue().isObject()) {
JsonObject myMemberObj = myMember.getValue().asObject();
for (JsonObject.Member nestedMember : myMemberObj) {
if(nestedMember.getName().equals("years")) {
myObj.set(myMember.getName(), nestedMember.getValue());
break;
}
}
}
}
}
System.out.println(jsonArray);
The last line when I print out my jsonArray, it looks as if nothing has changed whatsoever. What am I doing wrong? I want to end up with the following:
[{
name: John,
age: 18
computer_skills: 4
mile_runner: 2
}]
I tried using this: https://github.com/ralfstx/minimal-json. Alternatives are welcome. I want to not have to create a model object that contains key value pairs for every single key value in my object within "myarray". I am used to python where everything is simple to access and replace.
After some researching I found out that your json array is invalid, there are quotes missing on at least the keys (See why do you need the quotes). Look at the same code you used but with modified input for 'myarray':
String myarray = "[{\"name\":\"John\",\"age\":{\"years\":18},\"computer_skills\":{\"years\":4},\"mile_runner\":{\"years\":2}}]";
JsonArray jsonArray = JsonArray.readFrom(myarray);
for( JsonValue val : jsonArray) {
JsonObject myObj = val.asObject();
for( JsonObject.Member myMember : myObj ) {
if(myMember.getValue().isObject()) {
JsonObject myMemberObj = myMember.getValue().asObject();
for (JsonObject.Member nestedMember : myMemberObj) {
if(nestedMember.getName().equals("years")) {
myObj.set(myMember.getName(), nestedMember.getValue());
break;
}
}
}
}
}
System.out.println(jsonArray);
This code prints:
[{"name":"John","age":18,"computer_skills":4,"mile_runner":2}]
what is the expected result.

Categories

Resources