Print a jsonObject in a certain order - java

Is it possible to print a jsonObject in a certain order?
This is what I have
import NPC.NPCHandler;
import NPC.NPCDrops;
import com.google.gson.*;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import java.io.FileWriter;
/**
* #author Ruud.
*/
public class Main {
public static NPCDrops npcDrops = new NPCDrops();
public static NPCHandler npcHandler = new NPCHandler();
public static void main(String args[]) {
/*for (int i = 1; i < npcs.length; i++)
System.out.println(npcs[i].absX);*/
JSONObject NPCDefinition = new JSONObject();
NPCDefinition.put("New", "Tester");
NPCDefinition.put("B", "Test");
NPCDefinition.put("A", "Test");
NPCDefinition.put("Test", "Tester");
JSONArray NPCDefinitions = new JSONArray();
NPCDefinitions.add(0, NPCDefinition);
//NPCDefinitions.add(1, NPCDefinition);
try (FileWriter file = new FileWriter("./Json/NPCDefinitions.json")) {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
JsonParser jp = new JsonParser();
JsonElement je = jp.parse(NPCDefinitions.toJSONString());
String prettyJsonString = gson.toJson(je);
System.out.println(prettyJsonString);
//file.write(prettyJsonString);
} catch (Exception e) {
e.printStackTrace();
}
}
}
This is what it returns
[
{
"New": "Tester",
"A": "Test",
"B": "Test",
"Test": "Tester"
}
]
Is it possible to return it like the way it was put into the object?
I want this, because I am converting an NPC system in a game to a new better system using JSON, but I want the order to be in a human-logical way, like
[
{
"id": 0,
"name": "Hans",
"examine": "Servant of the Duke of Lumbridge.",
"combat": 0,
"size": 1
},
{
"id": 1,
"name": "Man",
"examine": "One of many citizens.",
"combat": 2,
"drops": [
{
"id": 995,
"amount": "1000",
"chance": 0.50
},
{
"id": 4151,
"amount": "1",
"chance": 1
}
],
"size": 1
}
]
I didn't test it yet with these variables, but I am sure it will mess up the order too, so I want to know if there is a way to keep this order. I know this isn't possible with JSONObject, because it is an unordered list or something, but this can't be achieved in any other way?

JSON objects are unordered K/V sets, but it does not mean that strict order is required, therefore it can be fully implementation driven.
What you're missing here is mixing two different libraries: JSON Simple and Gson. I have never worked with JSON Simple before, but even a quick look to that library would reveal that its org.json.simple.JSONObject extends raw HashMap which order may differ in different JRE versions. Unlike org.json.simple.JSONObject, Gson's native com.google.gson.JsonObject preserves the insertion order (see more at JsonObject implementation -- just because it's implemented this way). The same mixing story goes to org.json.simple.JSONArray and com.google.gson.JsonArray. So, the easiest solution is just getting rid of JSON Simple in favor of not mixing two different libraries, and just using Gson facilities, like this:
private static final Gson gson = new GsonBuilder()
.setPrettyPrinting()
.create();
public static void main(final String... args) {
final JsonObject npcDefinition = new JsonObject();
npcDefinition.addProperty("New", "Tester");
npcDefinition.addProperty("B", "Test");
npcDefinition.addProperty("A", "Test");
npcDefinition.addProperty("Test", "Tester");
final JsonArray npcDefinitions = new JsonArray();
npcDefinitions.add(npcDefinition);
final String json = gson.toJson(npcDefinitions);
System.out.println(json);
}
Also note, that no toString() invocation is necessary (it may be really expensive due to in-memory string allocations) here because Gson works with its JsonElement sub-classes just perfect. Thus, the original order is preserved:
[
{
"New": "Tester",
"B": "Test",
"A": "Test",
"Test": "Tester"
}
]
Since the objects are meant to be unordered, you should not really rely even on this implementation (I'm using Gson 2.8.0) -- what if someday a newer Gson implementation would break this rule and break the backwards compatibility in a major release (let's say, hypothetic Gson 3) for whatever reason? This seems to be relevant to serializers/deserializers that use reflection to produce/consume JSON (for example, ReflectiveTypeAdapterFactory). In order to guarantee the order, the most robust solution I could think of is direct write to output streams, say something like this:
#SuppressWarnings("resource")
public static void main(final String... args)
throws IOException {
final JsonWriter jsonWriter = new JsonWriter(new OutputStreamWriter(System.out));
jsonWriter.setIndent(" ");
jsonWriter.beginArray();
jsonWriter.beginObject();
jsonWriter.name("New").value("Tester");
jsonWriter.name("B").value("Tester");
jsonWriter.name("A").value("Tester");
jsonWriter.name("Test").value("Tester");
jsonWriter.endObject();
jsonWriter.endArray();
jsonWriter.flush();
}
[
{
"New": "Tester",
"B": "Tester",
"A": "Tester",
"Test": "Tester"
}
]

JSON-Objects don't care about order of their attributes.
It may be that there are implementations of JSON-libraries that handle the input order. But I do not suggest to rely on the input order handled by any JSON-library as an JSON-Object is and should remain the assertion to be associative (key-value) and the keys are unordered.
So there is no intrinsic possibility to preserve the input order. The only way is to simulate it: You have to remember an order id and write your own ouputter that considers the order id during output.

The way you define your model will impact the order of your serialisation to Json. Something like this should work :
public class MyModel {
public int id;
public string name;
public string examine;
public int combat;
public List<Drop> drops;
public int size;
}

Related

Parsing JSON Android ArrayList

I apologize if the title of my question is a bit misleading.
I created a POJO to hold CholesterolInformation about a user (HDL, LDL, Triglycerides, units, etc...). I now want to use my JSONObject to create an ArrayList so that I can generate some data points.
My JSONObject contains the following:
{
"cholesterol": [
{
"date": "2014-01-01",
"hdl": "56464.0",
"ldl": "46494.0",
"triGlycaride": "0.0",
"uid": "email#email.com",
"unit": "mg"
},
{
"date": "2014-01-01",
"hdl": "5.0",
"ldl": "5.0",
"triGlycaride": "0.0",
"uid": "email#email.com",
"unit": "mg"
},
{
"date": "2014-01-01",
"hdl": "6.0",
"ldl": "6.0",
"triGlycaride": "0.0",
"uid": "email#email.com",
"unit": "mg"
}
]
}
My question is, how would one go about iterating through this JSON Object? I would like to maybe use a for each, and create a new object to add to the ArrayList in each iteration... Do you have any advice or suggestions?
Note: I have never used the JSONObject before, and thus am not too familiar with its usage.
EDIT: Thanks everybody, that was exactly what I was looking for. I need to get more familiar with JSON manipulation. And I will look into GSON as well!
Use GSON as suggested by Eric as you already created POJO.
Gson gson = new Gson();
Type type = new TypeToken<List<POJO>>() {}.getType();
List<POJO> mList = gson.fromJson(your_json_string_here, type);
It's time to learn some JSON manipulation:
JSONArray array = yourJsonObject.optJSONArray("cholesterol");
if (array != null) {
for (int i=0; i< array.length; i++) {
JSONObject object = array.optJSONObject(i);
if (object != null) {
// this is where you manipulate all the date, hdl, ldl...etc
}
}
}
you also should check for null before accessing the json
If I understand you correctly, you want to create an ArrayList of your POJO? I assume you have getters and setters inside your POJO class. Initialize an ArrayList somewhere near the top like this
private ArrayList<CholesterolInformation> mCholesterol;
Now, parse through your json like this
JSONobject data = new JSONObject(jsonStringData);
JSONArray cholesterol = data.getJSONArray("cholesterol");
for(int i = 0; i < cholesterol.length; i++)
{
JSONObject object = cholesterol.getJSONObject(i);
// Create a new object of your POJO class
CholesterolInformation ci = new CholesterolInformation();
// Get value from JSON
String date = object.getString("date");
// Set value to your object using your setter method
ci.setDate(date);
String hdl = object.getString("hdl");
ci.setHdl(hdl);
.....
.....
// Finally, add the object to your arraylist
mCholesterol.add(ci);
}

Parsing generic tag in JSON from GSON

I have a JSON which contains generic values. I tried it by using Maps but couldn't get the results. My problem is the generic tags starts from second level. Here is the JSON I am trying to parse through gson.
{
"success": true,
"status": 200,
"events": {
"Sep 2013": [
{
"artist_id": 1,
"created_at": "2013-05-18T15:21:00Z",
"duration": 2,
"end_time": "2013-09-19T22:00:00Z",
"event_desc": "",
"event_facebook_link": "",
"event_link": "https://www.smtickets.com/marketing/view/1316",
"feature_small": false,
"featured_status": false,
"id": 90,
In this JSON tag after "events" is generic i.e., "Sep 2013".
What I am trying right now is:
public Event event ;
public class Event {
public ArrayList<Map<String, String>> dates;
}
And I'm accessing it:
obj = gson.fromJson(reader, AllShowsActivityData.class);
Can anyone tell me that how can I make a class of dates. So Gson can serialize it. Or is there any other way to iterate first level tag and then I can declare it something like this
Type fooType = new TypeToken<Foo<Bar>>() {}.getType();
gson.toJson(foo, fooType);
You can indeed use a Map, but you're not using it correctly. Note that what you have is a field "events", which is an object that contains a number of pairs string and array of objects:
{ "events": { "Sep 2013": [ {}, {}, ... ], ... } }
To parse your JSON you'd need a class structure like this (in pseudo-code):
class AllShowsActivityData
Map<String, List<Event>> events
class Event
int artist_id
String created_at //parsing as String to simplify...
int duration
...
And then your code to parse:
AllShowsActivityData obj = gson.fromJson(reader, AllShowsActivityData.class);
And finally, if what you want is to access the dates, you'll have all of them in:
Set<String> dates = obj.getEvents().keySet(); //"Sep 2013", ...
Note: in fact, if you only want those dates, you don't even need the class Event and you could use just Map<String, List<Object>> events...

Different JSON array response

I have problems parsing two different JSON responses.
1: This is the JSON response I get from a RESTful API:
{
"gear": [
{
"idGear": "1",
"name": "Nosilec za kolesa",
"year": "2005",
"price": "777.0"
}, {
"idGear": "2",
"name": "Stresni nosilci",
"year": "1983",
"price": "40.0"
}
]
}
2: This response I get from my testing client. I was added some values to the list and then I used gson.toJson for testing output.
[
{
"idGear": "1",
"name": "lala",
"year": 2000,
"price": 15.0
}, {
"idGear": "2",
"name": "lala2",
"year": 2000,
"price": 125.0
}
]
They are both valid, but the second one was successfully deserialize to object like this:
Type listType = new TypeToken<List<Gear>>() {}.getType();
List<Gear> gears= (List<Gear>) gson.fromJson(json, listType);
With the first one, I was trying to deserialize the same way but I get error.
EDIT
API Method:
#GET
#Produces(MediaType.APPLICATION_JSON)
public List<Gear> getGear() {
List<Gear> gears = gearDAO.getGears();
if (!gears.isEmpty()) {
return gears;
} else
throw new RuntimeException("No gears");
}
CLIENT serialization code:
List<Gear> list = new ArrayList<Gear>();
Gear o = new Gear();
o.setPrice(15);
o.setYear(2000);
o.setName("asds");
Type listTypes = new TypeToken<List<Gear>>() {}.getType();
gson.toJson(list, listTypes);
The JSON responses are different!
The first one is an object, surrounded by { }, which contains a field "gear" that is in turn a list of objects, surrounded by [ ].
The second one is directly a list of objects, because it's surrounded by [ ]. Namely, the whole 2nd response is equivalent to the field in the 1st response.
So, obviously they can't be parsed in the same way...
The 2nd one is being parsed correctly because you are using a List and it is a list. But for the 1st one you need another class that contains a field that contains in turn a list... That is, you just need to create a class structure that represents your JSON responses...
public class Response {
private List<Gear> gears;
//getters & setters
}
Now you can parse your 1st response with:
Gson gson = new Gson();
Response response = gson.fromJson(json, Response .class);
List<Gear> gears = response.getGears();
I suggest you to take a brief look at json.org in order to understand JSON syntax, which is pretty simple...
Basically these are the possible JSON elements:
object
{}
{ members }
members
pair
pair , members
pair
string : value
array
[]
[ elements ]
elements
value
value , elements
value
string
number
object
array
true
false
null

Is there any tool to generate a String from a JSON?

My doubt is if there is any tool on-line or not to generate a string from a JSON. For example, I have this JSON:
{
"my_json": [
{
"number": 20,
"name": "androider",
},
{
"id": 3432,
"name": "other_name",
}
]
}
If I want to declare a String in my code with this values, so I have to write many quotation marks to have my JSON in a String acceptable format.
So I want to know if thre is some tool to generate this String?
Some good choices are:
Jackson
Gson
They have built in methods to do just whatever you need to do in an efficient way...
I can't quite tell what you want from your original question, but I assume you are trying to output a Java String that contains some JSON that you have generated.
You should use JSONObject and JSONArray to accomplish this.
To create this JSON:
{
"my_json": [
{
"number": 20,
"name": "androider",
},
{
"id": 3432,
"name": "other_name",
}
]
}
You should use this code:
JSONObject a = new JSONObject();
a.put("number", 20);
a.put("name", "androider");
JSONObject b = new JSONObject();
b.put("id", 3432);
b.put("name", "other_name");
JSONArray array = new JSONArray();
array.put(a);
array.put(b);
JSONObject root = new JSONObject();
root.put("my_json", array);
// convert the root object to a string with 4 spaces of indentation
String json = root.toString(4);
As told by Angel, Jackson and Gson are two cool libs.
Gson is very easy to use while Jackson has better performance.
Try here, Go through the answers mentioned below
How to convert String to JSONObject in Java
in short,
Using org.json library:
JSONObject jsonObj = new JSONObject("{\"phonetype\":\"N95\",\"cat\":\"WP\"}");
Here put your own string.
Edit:
Try here,
http://www.mkyong.com/java/json-simple-example-read-and-write-json/
Create a Json object,
JSONObject jsonobj = new JSONObject();
Put your data using...
josnobj.put()

Gson - convert from Json to a typed ArrayList<T>

Using the Gson library, how do I convert a JSON string to an ArrayList of a custom class JsonLog? Basically, JsonLog is an interface implemented by different kinds of logs made by my Android app--SMS logs, call logs, data logs--and this ArrayList is a collection of all of them. I keep getting an error in line 6.
public static void log(File destination, JsonLog log) {
Collection<JsonLog> logs = null;
if (destination.exists()) {
Gson gson = new Gson();
BufferedReader br = new BufferedReader(new FileReader(destination));
logs = gson.fromJson(br, ArrayList<JsonLog>.class); // line 6
// logs.add(log);
// serialize "logs" again
}
}
It seems the compiler doesn't understand I'm referring to a typed ArrayList. What do I do?
You may use TypeToken to load the json string into a custom object.
logs = gson.fromJson(br, new TypeToken<List<JsonLog>>(){}.getType());
Documentation:
Represents a generic type T.
Java doesn't yet provide a way to represent generic types, so this class does. Forces clients to create a subclass of this class which enables retrieval the type information even at runtime.
For example, to create a type literal for List<String>, you can create an empty anonymous inner class:
TypeToken<List<String>> list = new TypeToken<List<String>>() {};
This syntax cannot be used to create type literals that have wildcard parameters, such as Class<?> or List<? extends CharSequence>.
Kotlin:
If you need to do it in Kotlin you can do it like this:
val myType = object : TypeToken<List<JsonLong>>() {}.type
val logs = gson.fromJson<List<JsonLong>>(br, myType)
Or you can see this answer for various alternatives.
Your JSON sample is:
{
"status": "ok",
"comment": "",
"result": {
"id": 276,
"firstName": "mohamed",
"lastName": "hussien",
"players": [
"player 1",
"player 2",
"player 3",
"player 4",
"player 5"
]
}
so if you want to save arraylist of modules in your SharedPrefrences so :
1- will convert your returned arraylist for json format using this method
public static String toJson(Object jsonObject) {
return new Gson().toJson(jsonObject);
}
2- Save it in shared prefreneces
PreferencesUtils.getInstance(context).setString("players", toJson((.....ArrayList you want to convert.....)));
3- to retrieve it at any time get JsonString from Shared preferences like that
String playersString= PreferencesUtils.getInstance(this).getString("players");
4- convert it again to array list
public static Object fromJson(String jsonString, Type type) {
return new Gson().fromJson(jsonString, type);
}
ArrayList<String> playersList= (ArrayList<String>) fromJson(playersString,
new TypeToken<ArrayList<String>>() {
}.getType());
this solution also doable if you want to parse ArrayList of Objects
Hope it's help you by using Gson Library .
Why nobody wrote this simple way of converting JSON string in List ?
List<Object> list = Arrays.asList(new GsonBuilder().create().fromJson(jsonString, Object[].class));
Kotlin
data class Player(val name : String, val surname: String)
val json = [
{
"name": "name 1",
"surname": "surname 1"
},
{
"name": "name 2",
"surname": "surname 2"
},
{
"name": "name 3",
"surname": "surname 3"
}
]
val typeToken = object : TypeToken<List<Player>>() {}.type
val playerArray = Gson().fromJson<List<Player>>(json, typeToken)
OR
val playerArray = Gson().fromJson(json, Array<Player>::class.java)
If you want to use Arrays, it's pretty simple.
logs = gson.fromJson(br, JsonLog[].class); // line 6
Provide the JsonLog as an array JsonLog[].class
If you want convert from Json to a typed ArrayList , it's wrong to specify the type of the object contained in the list. The correct syntax is as follows:
Gson gson = new Gson();
List<MyClass> myList = gson.fromJson(inputString, ArrayList.class);
Let's say, You have a string like this.
"[{"id":2550,"cityName":"Langkawi","hotelName":"favehotel Cenang Beach - Langkawi","hotelId":"H1266070"},
{"id":2551,"cityName":"Kuala Lumpur","hotelName":"Metro Hotel Bukit Bintang","hotelId":"H835758"}]"
Then you can covert it to ArrayList via Gson like
var hotels = Gson().fromJson(historyItem.hotels, Array<HotelInfo>::class.java).toList()
Your HotelInfo class should like this.
import com.squareup.moshi.Json
data class HotelInfo(
#Json(name="cityName")
val cityName: String? = null,
#Json(name="id")
val id: Int? = null,
#Json(name="hotelId")
val hotelId: String? = null,
#Json(name="hotelName")
val hotelName: String? = null
)
I am not sure about gson but this is how you do it with Jon.sample hope there must be similar way using gson
{
"Players": [
"player 1",
"player 2",
"player 3",
"player 4",
"player 5"
]
}
===============================================
import java.io.FileReader;
import java.util.List;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
public class JosnFileDemo {
public static void main(String[] args) throws Exception
{
String jsonfile ="fileloaction/fileName.json";
FileReader reader = null;
JSONObject jsb = null;
try {
reader = new FileReader(jsonfile);
JSONParser jsonParser = new JSONParser();
jsb = (JSONObject) jsonParser.parse(reader);
} catch (Exception e) {
throw new Exception(e);
} finally {
if (reader != null)
reader.close();
}
List<String> Players=(List<String>) jsb.get("Players");
for (String player : Players) {
System.out.println(player);
}
}
}
In Kotlin
For sending : If you send Arraylist
Gson().toJson(arraylist)
For receiving: If you receive ArrayList
var arraylist = Gson().fromJson(argument, object : TypeToken<ArrayList<LatLng>>() {}.type)
For sending : If you send ModelClass( e.g. LatLngModel.class)
var latlngmodel = LatlngModel()
latlngmodel.lat = 32.0154
latlngmodel.lng = 70.1254
Gson().toJson(latlngModel)
For receiving: If you receive ModelClass
var arraylist = Gson().fromJson(argument,LatLngModel::class.java )

Categories