Parsing json into a nested ArrayList in libgdx - java

I was using Jackson for all my json serialisation and deserialisation, but I'm trying to get my game working with GWT now so I'm moving over to the libgdx json parsing libraries.
Everything seems ok so far except this
HashMap<String, ArrayList<HighScoreEntry>> high_scores =
new HashMap<String, ArrayList<HighScoreEntry>>();
The ArrayList within the hashmap is being created as a array of JsonValue rather than an array of HighScoreEntry.
Can someone explain how I work around this? I know about json.setElementType(); but can't see how to use it in this instance. I'm playing with writing custom serialisation, but again, I can't work out how to extract exactly what I need.
I'm guessing in a custom serialiser I can use
json.readFields(this, jsonData);
to populate everything and then correct the erroneous data afterwards.
HighScoreEntry class (without methods):
public class HighScoreEntry implements Comparable<HighScoreEntry>, java.io.Serializable {
public long id;
public int score;
public String language = "en";
public String data;
public String name;
public boolean current;
}
Pointers would be appreciated.

I've worked something out, but I feel like there must be a better way. If anyone else has any ideas then please post them.
Adding a custom reader I can correct the corrupted high scores and convert them into instances of HighScoreEntry objects.
#Override
public void read(Json json, JsonValue jsonData) {
// Read all the fields
json.readFields(this, jsonData);
// replace high scores
HighScoreHashMapJsonValue screwedUpHashMap = json.readValue(HighScoreHashMapJsonValue.class, jsonData.get("high_scores"));
HashMap<String, Array<HighScoreEntry>> newHighScores = new HashMap<String, Array<HighScoreEntry>>();
for (Map.Entry<String, Array<JsonValue>> entry : screwedUpHashMap.entrySet()) {
String key = entry.getKey();
Array<JsonValue> jsonValueHighScores = entry.getValue();
Array<HighScoreEntry> highScoreArray = new Array<HighScoreEntry>();
newHighScores.put(key, highScoreArray);
for (JsonValue highScore : jsonValueHighScores) {
highScoreArray.add(json.readValue(HighScoreEntry.class, highScore));
}
}
high_scores = newHighScores;
}
public static class HighScoreHashMapJsonValue extends HashMap<String, Array<JsonValue>> {
}

Related

Deserialize dynamic fields with GSON into POJO

I've tried so many ways, but without success to parse this Json to a Java Object using Gson library:
"return":{
"48388":{
"status":"canceled",
"operations":{
},
"created":"138232386",
"price":"12.50000",
"volume":"50.00000000",
"pair":"btc_brl",
"type":"buy"
},
"51714":{
"status":"canceled",
"operations":{
},
"created":"1365465421706",
"price":"1500.00000",
"volume":"0.10000000",
"pair":"btc_brl",
"type":"buy"
},
"48754":{
"status":"canceled",
"operations":{
},
"created":"1383237058",
"price":"600.00000",
"volume":"0.50000000",
"pair":"btc_brl",
"type":"buy"
}
"success":1
}
There is a lot of topics about this, but none of them cover this type of json mapping.
I'm convinced that there is a simple way to do that, any ideas? Thanks!
EDIT:
I'm trying this:
public class Test {
#SerializedName("return")
public Return1 _return;
}
public class Return {
public List<Map<String, Order>> order;
}
EDIT:
public class Order {
#SerializedName("id")
private int idOrder;
private String status;
private String created;
private String price;
private String volume;
private String pair;
private String type;
private List<Operations> operations;
// All the gets and sets here..
}
Gson doesn't initialize my order object. The order object is always null. I can't find the correct way to implement this mapping.
After a long battle I was able to solve using this solution:
public void deserialize() {
Gson gson = new Gson();
// For isr read InputStreamReader
Map<String, Object> map = gson.fromJson(isr, Map.class);
System.out.println(map.get("success"));
Map<String, Object> map2 = (Map<String, Object>) map.get("return");
// Show the contents of return
System.out.println(map2);
}
After that I used an Entry object to iterate and set the values of Order.
Thanks!

use GSON in jsp page

I'm trying to serialize an object in JSON using a JSP like format using the following code:
ArrayList<AccountBean> al = new ArrayList<AccountBean>();
al = vc.getAccountName();
int i=0;
out.print("[");
while(i<al.size()){
Gson gson = new GsonBuilder().setPrettyPrinting().create();
out.print("{ID"+al.get(i).getAno()+":name"+al.get(i).getAccount_name()+"},");
i++;
}
out.print("]");
I'm getting a output like this:
[{ID1:nameEquity Share Capitals},{ID2:nameCalls In Arear},]
but my requirement is something like this:
[{"ID1":"nameEquity Share Capitals"},{"ID2":"nameCalls In Arear"}]
out.print('{"ID'+al.get(i).getAno()+'":"name'+al.get(i).getAccount_name()+'"},')
use ' to open/close the string, and " to wrap your json keys/values.
Otherwise you can do like this
out.print("{\"ID"+al.get(i).getAno()+"\":\"name"+al.get(i).getAccount_name()+"\"},")
escaping the quotes with \"
Anyway, have you tried this?
String json = gson.toJson(al)
Have a look here for more info: https://sites.google.com/site/gson/gson-user-guide
Best way to do this is using a custom serializer and I can edit this answer posting one if you want to go deeper.
However, since you are quite new to JSON and Gson I would answer with this simple code that you can paste&try in you IDE. I just "convert" you bean into a map, and the use Gson to serialize.
package stackoverflow.questions;
import java.util.*;
import com.google.gson.Gson;
public class Q20323412 {
public static class AccountBean{
Integer _id;
String _name;
public String getAccount_name(){
return _name;
}
public Integer getAno(){
// what a weird name, in italian for this method..
return _id;
}
public AccountBean(Integer id, String name){
_id = id;
_name = name;
}
}
/**
* #param args
*/
public static void main(String[] args) {
ArrayList<AccountBean> al = new ArrayList<AccountBean>();
al.add(new AccountBean(1, "Equity Share Capitals"));
al.add(new AccountBean(2, "Calls In Arear"));
ArrayList<Map> al2 = new ArrayList<>();
for(AccountBean account : al){
HashMap hm = new HashMap();
hm.put("ID"+ account.getAno(), "name"+account.getAccount_name());
al2.add(hm);
}
Gson g = new Gson();
System.out.println(g.toJson(al2));
}
}
Since you did not post your bean, I invented one that has features similar to your's.

jackson delay deserializing field

I have a class like this:
public class DeserializedHeader
int typeToClassId;
Object obj
I know what type of object obj is based on the typeToClassId, which is unfortunately only known at runtime.
I want to parse obj out based on typeToClassId - what's the best approach here? Annotations seem like they're out, and something based on ObjectMapper seems right, but I'm having trouble figuring out what the best approach is likely to be.
Something along the lines of
Class clazz = lookUpClassBasedOnId(typeToClassId)
objectMapper.readValue(obj, clazz)
Obviously, this doesn't work since obj is already deserialized... but could I do this in 2 steps somehow, perhaps with convertValue?
This is really complex and painful problem. I do not know any sophisticated and elegant solution, but I can share with you my idea which I developed. I have created example program which help me to show you how you can solve your problem. At the beginning I have created two simple POJO classes:
class Product {
private String name;
// getters/setters/toString
}
and
class Entity {
private long id;
// getters/setters/toString
}
Example input JSON for those classes could look like this. For Product class:
{
"typeToClassId" : 33,
"obj" : {
"name" : "Computer"
}
}
and for Entity class:
{
"typeToClassId" : 45,
"obj" : {
"id" : 10
}
}
The main functionality which we want to use is "partial serializing/deserializing". To do this we will enable FAIL_ON_UNKNOWN_PROPERTIES feature on ObjectMapper. Now we have to create two classes which define typeToClassId and obj properties.
class HeaderType {
private int typeToClassId;
public int getTypeToClassId() {
return typeToClassId;
}
public void setTypeToClassId(int typeToClassId) {
this.typeToClassId = typeToClassId;
}
#Override
public String toString() {
return "HeaderType [typeToClassId=" + typeToClassId + "]";
}
}
class HeaderObject<T> {
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
#Override
public String toString() {
return "HeaderObject [obj=" + obj + "]";
}
}
And, finally source code which can parse JSON:
// Simple binding
Map<Integer, Class<?>> classResolverMap = new HashMap<Integer, Class<?>>();
classResolverMap.put(33, Product.class);
classResolverMap.put(45, Entity.class);
ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
String json = "{...}";
// Parse type
HeaderType headerType = mapper.readValue(json, HeaderType.class);
// Retrieve class by integer value
Class<?> clazz = classResolverMap.get(headerType.getTypeToClassId());
// Create dynamic type
JavaType type = mapper.getTypeFactory().constructParametricType(HeaderObject.class, clazz);
// Parse object
HeaderObject<?> headerObject = (HeaderObject<?>) mapper.readValue(json, type);
// Get the object
Object result = headerObject.getObj();
System.out.println(result);
Helpful links:
How To Convert Java Map To / From JSON (Jackson).
java jackson parse object containing a generic type object.

HashMap get an element and set into customized value type

I have a problem while I set get an element and set into customized value type.
Here is my customized type class User
public class User {
private List<Integer> FriendList=new ArrayList<Integer>(); //Uid list
private HashMap<String,String> CheckinMap =new HashMap<String, String>(); // location and time
private int Uid;
public User(int uid){
this.Uid=uid;
}
public int getId(){
return Uid;
}
public void setCheckins(HashMap<String,String> InMap){
this.CheckinMap=(HashMap<String, String>) InMap;
}
public void setAFriend(int uid){
this.FriendList.add(uid);
}
}
Then, I parse a JSON array to get data, I am sure that parsing JSON is fine here.
HashMap<Integer,User> UserMap =new HashMap();
HashMap<String,String> InMap =new HashMap();
for(i=0;i<users.size();i++){
JSONObject auser=(JSONObject)users.get(i);
temp_uid=Integer.parseInt(auser.get("uid").toString());
UserMap.put(temp_uid, new User(temp_uid));
JSONArray checkins=(JSONArray)auser.get("check-ins");
for(j=0;j<checkins.size();j++){
InMap.put( ((ArrayList) checkins.get(j)).get(0).toString(), ((ArrayList) checkins.get(j)).get(1).toString());
}
UserMap.get(i).setCheckin(InMap);
checkin_cnt=checkin_cnt+checkins.size();
}
My Eclipse told me that an exception java.lang.NullPointerExceptionis at the line.
UserMap.get(i).setCheckin(InMap);
Can I only initialize Uid , but set FriendList and CheckinMap later? This sounds wired.
Please give me some hints or suggestions. Thanks
From this code I should assume that auser's UID is always the same as it's index.
If my assumption is wrong, this is a reason, You should ask for UserMap.get(temp_uid) not UserMap.get(i)

Best technique to map JSON data into ContentValues

I'm developing an Android app which will initiate a number of API calls that return JSON data structures and then store the results in a content provider. Different API calls return different JSON data structures and map to a corresponding table schema in the content provider. I'm looking for a simple and Java-esque method to map from the properties in a JSONObject to a flat ContentValues object. I started to use a simple HashMap and iterating over it's entrySet mapping key strings in the JSONObject to value strings for the ContentValues object, but I'd like to account for the fact that some JSON properties are integers or booleans. Also, in some cases I'd like a more complex mapping such as a JSONArray into a comma separated string. In C, I'd probably just do this with a struct array name, value, type, and an optional callback to handle more complex mappings.
UPDATE: Due to the hierarchal nature of the JSON Data Structure and due to the fact that it can actually have sub-tables at certain depths I've taken the following approach.
private static interface MapJSON {
public void mapData(JSONObject object, ContentValues values)
throws JSONException;
}
private static abstract class AbstractMapJSON implements MapJSON {
protected final String mJSONName;
protected final String mContentName;
public AbstractMapJSON(String jsonName, String contentName) {
mJSONName = jsonName;
mContentName = contentName;
}
public abstract void mapData(JSONObject object, ContentValues values)
throws JSONException;
}
/* This is the basic template for each of the basic types */
private static class BooleanMapJSON extends AbstractMapJSON {
public BooleanMapJSON(String jsonName, String contentName) {
super(jsonName, contentName);
}
public void mapData(JSONObject object, ContentValues values)
throws JSONException {
values.put(mContentName, object.getBoolean(mJSONName));
}
}
/* This class takes a nested JSON Object and flattens it into the same table */
private static class ObjectMapJSON implements MapJSON {
protected final String mJSONName;
protected final MapJSON[] mMap;
public ObjectMapJSON(String jsonName, MapJSON[] map) {
mJSONName = jsonName;
mMap = map;
}
public void mapData(JSONObject object, ContentValues values)
throws JSONException {
JSONObject subObject = object.getJSONObject(mJSONName);
for(MapJSON mapItem: mMap) {
mapItem.mapData(subObject, values);
}
}
}
With that defined, I've can create mappings like this:
private static final MapJSON[] mainSiteMap = new MapJSON[] {
new StringMapJSON("name", StackPad.Sites.NAME),
new LongMapJSON("creation_date", StackPad.Sites.CREATION_DATE),
new StringMapJSON("description", StackPad.Sites.DESCRIPTION),
};
private static final MapJSON sitesMap = new ObjectMapJSON("main_site", mainSiteMap);
But it still seems like it needs a little work to mesh well.
Maybe you can build a class and use it in the hashmap , I dont know whats your types but for example
class Foo{
String name;
String value;
String type;
int opt;
}
.....
HashMap hm = new HashMap();
Foo foo = new Foo("123","123","type",1);
hm.put("100", foo);
.....
you can try using google's gson, create a structure for your object then map them to the object.. you can specify what datatype and support primitive types as well..

Categories

Resources