From a given Map to a json string (or JSONObject) - java

In Java, I've these key/value pairs passed by post (for example):
form_id=undefined
frmb[0][cssClass]=input_text
frmb[0][required]=checked
frmb[0][values]=First Name
frmb[1][cssClass]=input_text
frmb[1][required]=checked
frmb[1][values]=Last Name
frmb[2][cssClass]=textarea
frmb[2][required]=undefined
frmb[2][values]=Bio
frmb[3][cssClass]=checkbox
frmb[3][required]=undefined
frmb[3][title]=What's on your pizza?
frmb[3][values][2][baseline]=undefined
frmb[3][values][2][value]=Extra Cheese
frmb[3][values][3][baselise]=undefined
frmb[3][values][3][value]=Pepperoni
frmb[3][values][4][baseline]=undefined
frmb[3][values][4][value]=Beef
frmb[4][cssClass]=radio
frmb[4][required]=undefined
frmb[4][title]=Do you like pizza?
frmb[4][values][2][baseline]=checked
frmb[4][values][2][value]=Yes
frmb[4][values][3][baseline]=undefined
frmb[4][values][3][value]=No
frmb[5][cssClass]=select
frmb[5][multiple]=checked
frmb[5][required]=checked
frmb[5][title]=Select a pizza type:
frmb[5][values][2][baseline]=checked
frmb[5][values][2][value]=Margherita
frmb[5][values][3][baseline]=undefined
frmb[5][values][3][value]=Napoli
frmb[5][values][4][baseline]=undefined
frmb[5][values][4][value]=Marinara
I've to create the following json:
[{"cssClass":"input_text","required":"checked","values":"First Name"},{"cssClass":"input_text","required":"checked","values":"Last Name"},{"cssClass":"textarea","required":"undefined","values":"Bio"},{"cssClass":"checkbox","required":"undefined","title":"What's on your pizza?","values":{"2":{"value":"Extra Cheese","baseline":"undefined"},"3":{"value":"Pepperoni","baseline":"undefined"},"4":{"value":"Beef","baseline":"undefined"}}},{"cssClass":"radio","required":"undefined","title":"Do you like pizza?","values":{"2":{"value":"Yes","baseline":"checked"},"3":{"value":"No","baseline":"undefined"}}},{"cssClass":"select","required":"checked","multiple":"checked","title":"Select a pizza type:","values":{"2":{"value":"Margherita","baseline":"checked"},"3":{"value":"Napoli","baseline":"undefined"},"4":{"value":"Marinara","baseline":"undefined"}}}]
How could I do?
I don't succeed in parsing the keys, grouping the elements which do part of the same JSONObject.

You can use the Gson library for this. It does not support serializaton of nested maps (I assume your output represents a nested map). You can write a custom serializer/deserializer or create your own serialization method following the instructions in this thread

You can do something like this:
JSONArray jsonItems = new JSONArray();
for (int i = 0; i < frmb.size(); i++) {
JSONObject json = new JSONObject();
json.put("cssClass", frmb[i][cssClass]);
json.put("required",frmb[i][required]);
//put json object to json array
jsonItems.put(json);
}
Check here for more details

I resolved by parsing the keys and by building the JSONObjects with the use of two temporary hashtables.

Related

Why can't read a .json?

I want to read a .json using library json-simple, my json file is:
{
"Subjects": {
"subject1": "MIS",
"subject2": "DBMS",
"subject3": "UML"
}
}
And my code is:
import java.io.*;
import java.util.*;
import org.json.simple.*;
import org.json.simple.parser.*;
public class JSONReadFromTheFileTest {
public static void main(String[] args) {
JSONParser parser = new JSONParser();
try{
Object obj = parser.parse(new FileReader("/Users/User/Desktop/course.json"));
JSONObject jsonObject = (JSONObject)obj;
JSONArray subjects = (JSONArray)jsonObject.get("Subjects");
Iterator iterator = subjects.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}catch(Exception e){
e.printStackTrace();
}
}
}
I would like to get in console:
subject1: MIS
subject2: DBMS
subject3: UML
But instead of that, I just get the next error:
java.lang.ClassCastException: org.json.simple.JSONObject cannot be cast to org.json.simple.JSONArray
at project.Main(Main.java:11)
But I searched in internet, and I found that if I change sintaxys of the .json in the next way:
{
"Subjects": [
"subject1: MIS",
"subject2: DBMS",
"subject3: UML"
]
}
I get in console what I want:
subject1: MIS
subject2: DBMS
subject3: UML
And you may think my problem is solved, but not yet, because I want to read the json file in the first way.
I hope someone can help me. Thanks in advance.
The first example shows a Subjects key containing a single object with several properties (subject1, subject2, etc).
Consider those properties like the member variables of a class.
In order to let you better understand if the class is Person those variables could be name and surname.
What you try to achieve in your code is extracting a JSONArray from the JSON you are providing.
Going back to the example for Person the array could be - sorry for the silly example - an Array containing phone numbers.
So what you are expecting is that one of the member properties of the class is an array.
This is not possible in the first example because the first example does not contain a json array.
This line extracts the whole json object:
JSONObject jsonObject = (JSONObject)obj;
This one tries to get an array out but no array is there in the first example:
JSONArray subjects = (JSONArray)jsonObject.get("Subjects");
Square brackets represent an array, which you've casted the getter into.
The second json shown is more correct for the code you've written, however, arrays cannot hold key-value pairs, so that's why you've made second JSON have an array of strings
To parse the first file, you'd need to start with
JSONObject subjects = (JSONObject)jsonObject.get("Subjects")
If you have full control over the file, I'd suggest just storing ["MIS", "DBMS", "UML"] then write a simple loop
for (int i = 0; i < jsonArray.length; i++) {
System.out.printf("subject%d: %s%n", i+1, jsonArray.get(i));
}
To make your code work with your json, you should not use JSONArray for "Subjects" but instead JSONObject. The reason is that [ and ] indicates beginning and ending of array element in json which is represented by JSONArray. If you have { and } element then its object represented by JSONObject. zz So replace this:
JSONArray subjects = (JSONArray)jsonObject.get("Subjects");
Iterator iterator = subjects.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
with following (I have not compiled it):
JSONObject subjects = (JSONObject)jsonObject.get("Subjects");
for(Iterator iterator = subjects.keySet().iterator(); iterator.hasNext();) {
String key = (String) iterator.next();
System.out.println(key + ": " + subjects.get(key));
}
As others mentioned you should replace JSONArray with JSONObject in your code. But I would suggest to switch to different JSON library all together. I would recommend to use Json-Jackson library. Also, there is another library that provides a wrapper over Json-Jackson library. It has JsonUtils class that can simply parse your JSON in one line. Just read first your Json from file into a String jsonString and do this.
Map<String, Object> myMap = JsonUtils.readObjectFromJsonString(jsonString, Map.class);
You will get a Map with one key "Subjects" that will have a value of a Map with your 3 keys and values:
subject1: MIS
subject2: DBMS
subject3: UML
Here is the JavaDoc for the JsonUtils class. The library could be found as Maven artifact and on Github (including source code and Javadoc).

json (gson) parse changes the type of data when parsing

I have a json string which looks something like this :
{"employees":[
{"firstName":"John", "lastName":"Doe"},
{"firstName":"Anna", "lastName":"Smith"},
{"firstName":"Peter", "lastName":"Jones"}
]}
When I use gson parser to convert that to a Map<String,String> map. The gson converts the type to Map<String,ArrayList>. And when I try to print the class name using System.out.println(map.get("employees").getClass().toString()). But this throws an exception - java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.String.
my code looks something like this
String npv = json_string_provided_above;
Map<String,String> mp = new HashMap<String, String>();
mp = new Gson().fromJson(npv,mp.getClass());
System.out.println(mp.get("employees").getClass().toString());
The json is given as input by user in string format(and it will always be a valid json string). And one thing is sure that I can't assume anything about the type of data. Because it will be provided by user.
So now actually I want that even If the user inputs something like arrays of string or arrays of objects. It should not convert the them to List,
Is there is a way I can hard code the type and keep them in Map<String,String>. so in the above example when I do map.get("employees") it should give me the [{"firstName":"John", "lastName":"Doe"},{"firstName":"Anna", "lastName":"Smith"},{"firstName":"Peter", "lastName":"Jones"}] as string not list. I am not sure how to do this.
Thank you for your help,
Jon is right, just use Map<String, Object>
String npv = json_string_provided_above;
Map<String,Object> mp = new HashMap<String, Object>();
mp = new Gson().fromJson(npv, mp.getClass());
System.out.println(mp.get("employees").toString());

how to parse multiple json objects with no name

im having some trouble parsing json. I have json in the format of:
{"blah":"blah","blah":"blah"}
{"blah":"blah","blah":"blah"}
{"blah":"blah","blah":"blah"}
Here is the link to the JSON: http://gerrit.aokp.co/query?format=JSON&q=status:merged&age:1d
I cant make this a jsonobject and iterate over it. I currently have it as a string.
Is there a way to iterate over this? there will be over 500.
I tried making it an array by adding square brackets around it, but it didnt work because i needed to divide them with commas. I cant manipulate this by hand because im getting it from the web. So i tried this.
jsonString = jsonString.replaceAll("}(?!,)", "},");
the reason im adding the negative comma is that sometimes i might have a jsonobject inside of of these objects so I only want to add a comma in front of the '}' without commas.
when i do the replaceall i get this error.
Error in fetching or parsing JSON: java.util.regex.PatternSyntaxException: Syntax error in regexp pattern near index 1:
}(?!,)
^
What am I doing wrong or is there an easier way to do this that im looking over?
EDIT:
Oh yes, I need to implement this in java because this is in an android app.
here is an example how you can accomplish what you want using Jackson's ObjectMapper.
ObjectMapper om = new ObjectMapper();
try {
List<Object> obj = om.readValue(yourJsonString, new TypeReference<List<Object>> () { });
} catch (IOException e1) {
e1.printStackTrace();
}
Now you will have a list of each of the individual Objects in your JSON string. To take it a step further you could create a POJO for the Object you are parsing.
Something like:
public class MyObject{
private String project;
private String branch;
}
That is just an exmple, you would need to define a property for each json property.
Then you can turn :
List<Object> obj = om.readValue(yourJsonString, new TypeReference<List<Object>> () { });
Into
List<MyObject> obj = om.readValue(yourJsonString, new TypeReference<List<MyObject>> () { });
Hope this helps!
From the link you posted, it looks like there are newlines between objects (and only between objects). If that's right, I'd approach it like this:
String[] items = dataFromWeb.split("\n");
String asJSONArrayString = Arrays.toString(items);
JSONArray jsonArray = new JSONArray(asJSONArrayString);
This splits the data at newlines, then joins it together with commas between elements and brackets around the whole thing.
JSONObject jObject = null;
mJsonString = downloadFileFromInternet(urlString);
jObject = new JSONObject(mJsonString);
This will get you json object.
This is the way to get json array from json object:
JSONArray jsonImageArray = jObject.getJSONArray("your string");

Parse json use JsonOjbect vs map into entity with GSon

I'm looking for the right way to parse json use GSon library. Up to now, I have known 2 ways to do this:
Assume I have a json string like this:
{
'Events' : [{
'name' : 'exp',
'date' : '10-10-2010',
'tags' : ["tag 1", "tag2", "tag3"]
},...more events...],
'Contacts' : [{
'name' : 'John Smith',
'date' : '10-10-2010',
'tags' : ["tag 1", "tag2", "tag3"]
},...more contacts...],
}
Use JSonOjbect to get field by its name:
JsonElement jelement = new JsonParser().parse(jsonLine);
JsonObject jobject = jelement.getAsJsonObject();
jobject = jobject.getAsJsonArray("Events");
JsonArray jarray = jobject.getAsJsonArray("Contacts");
jobject = jarray.get(0).getAsJsonObject();
Use GSon to map into entity
public class Container{
List<Event> Events;
List<Contact> Contacts;
}
Container c = new GSon().fromJSon(jsonString,Container.class);
Could you tell me when I should use the first way or the second?
I have a web service could return many kinds of complex json string, and I need get data from this. What should I do?
According to the benchmarks, the first approach (GSON_DOM) is faster. This is likely because with the DOM approach you are only deserializing part of the JSON string. If you wanted even more performance you could switch to the GSON_STREAM approach which seems to do best in the benchmarks.
Practically, the second approach makes for simpler code. I would use probably use that approach first and then switch to one of the other methods if I find that JSON deserialization is taking a significant amount of time.

How can i sort Nested JSON Array?

How can i sort Nested JSON Array? Like for a JSON below...
{
"id":"rtmc05.lax.someabc.net",
"name":"rtmc05.lax.someabc.net",
"tenants":[{
"id":"rtmc",
"name":"rtmc"
},{
"id":"hrs",
"name":"hrs"
},{
"id":"amotelbe1",
"name":"amotelbe"
},{
"id":"cds",
"name":"cds"
},{
"id":"idx-server",
"name":"idx-server",
"tenants":[{
"id":"amotelbe",
"name":"amotelbe",
"tenants":[{
"id":"amotelui",
"name":"amotelui"
}]
}]
}]
}
There's a few parts implicit to your question, and it's not clear where you're having trouble:
How do you take a JSON string and make usable Java objects out of it. (I'm assuming Java, not JavaScript, since you've tagged your question with "java".)
How do you sort those objects after they're made?
How do you handle sorting the nested parts? (In your example, "idx-server" has sub-tenants.)
Not sure exactly which parts of this you're having trouble with, so here's some notes for all three.
Part 1: Getting Java objects
I agree with the other guy that Jackson is a good JSON parser to use. Here's a couple lines of code you could use to parse some JSON:
String jsonString = "..."; // Load this in whatever way makes sense for you
ObjectMapper mapper = new ObjectMapper();
Map<String,Object> parsedJson = mapper.readValue(jsonString, Map.class);
If your JSON string is really huge, then there are other readValue overloads that you can use to avoid reading the whole String into memory.
Part 2: Sorting Java objects
Once you've got the parsed JSON, sorting is just a matter of calling Collections.sort(...), passing in the tenants array. Plus you'll need to write a Comparator that defines the ordering that you want. For example, here's a comparator that sorts by name:
public class NameComparator implements Comparator<Map<String,Object>> {
public int compare(Map<String,Object> o1, Map<String,Object> o2) {
String name1 = (String) o1.get("name");
String name2 = (String) o2.get("name");
return name1.compareTo(name2);
}
}
Then you get the tenants array out (Jackson makes them into ArrayList objects) and call Collections.sort(...). For example,
List<Map<String,Object>> tenants =
(List<Map<String,Object>>) parsedJson.get("tenants");
Collections.sort(tenants, new NameComparator());
Part 3: Handling the nesting
The clearest way to do this is to add some extra code to walk through your JSON looking for any object with a tenants array, and sort it. For example, here's a recursive function that should do it:
public static void recursiveSortTenants(Map<String,Object> jsonObject) {
List<Map<String,Object>> tenants =
(List<Map<String,Object>>) jsonObject.get("tenants");
if (tenants != null) {
Collections.sort(tenants, new NameComparator());
// For each tenant, see if it has sub-tenants. If so,
// call this function again to sort them.
for (Map<String,Object> tenant : tenants) {
if (tenants.containsKey("tenants")) {
recursiveSortTenants(tenant);
}
}
}
}
Hope this helps!
Parse it into (javascript) objects then write a sort function that sorts an array of such javascript objects.
Deserialize it to POJOs(with Gson or Jackson), and write a Comparator for that POJOs.

Categories

Resources