I am trying to map a json document from the jenkins API to my own java objects. The json document looks as follows:
{
"assignedLabels": [
{}
],
"mode": "EXCLUSIVE",
"nodeDescription": "Jenkins Master-Knoten",
"nodeName": "",
"numExecutors": 2,
"description": null,
"jobs": [
{
"name": "Job 1",
"url": "https://build.example.com/jenkins/job/Job1/",
"color": "disabled"
},
{
"name": "Job 2",
"url": "https://build.example.com/jenkins/job/Job2/",
"color": "blue"
}
],
"overallLoad": {},
"primaryView": {
"name": "Alle",
"url": "https://build.example.com/jenkins/"
},
"quietingDown": false,
"slaveAgentPort": 0,
"unlabeledLoad": {},
"useCrumbs": false,
"useSecurity": true,
"views": [
{
"name": "Selection",
"url": "https://build.example.com/jenkins/view/-All%Selection/"
},
{
"name": "All",
"url": "https://build.example.com/jenkins/"
}
]
}
My java model looks like this:
public class JenkinsServer {
private List<String> assignedLabels;
private String url;
private String mode;
private String nodeName;
private String nodeDescription;
private String description;
private boolean useSecurity;
private boolean quietingDown;
private JenkinsServerView primaryView;
private List<JenkinsServerView> views;
private List<JenkinsJob> jobs;
// getters & setters
}
What I am doing now is I call
Gson gson = new Gson();
JenkinsServer server = gson.fromJson( reader, JenkinsServer.class );
But I receive this exception
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 6 column 5
at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:374)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:165)
I've been searching the internet for a solution but could not figure out what I'm doing wrong. Maybe you guys know :-)
As #Gimby mentioned in the comment, the problem is in your json data.
Solution1:
As assignedLabels is an array of strings with empty values, one option is to change the json data without curly braces as follows:
"assignedLabels": []
Solution2:
add transient keyword to the variable in java class
private transient List<String> assignedLabels;
Solution3:
the last and clumsy way to achieve is to add #Expose annotation to the all the variables that you want to parse in your java class
public class JenkinsServer {
private List<String> assignedLabels;
#Expose
private String url;
#Expose
private String mode;
#Expose
private String nodeName;
#Expose
private String nodeDescription;
#Expose
private String description;
#Expose
private boolean useSecurity;
#Expose
private boolean quietingDown;
#Expose
private JenkinsServerView primaryView;
#Expose
private List<JenkinsServerView> views;
#Expose
private List<JenkinsJob> jobs;
// getters & setters methods
}
and then add the parsing logic to parse your json string to corresponding java object as follows:
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
JenkinsServer server = gson.fromJson(reader, JenkinsServer.class);
Related
I here by mentioned the sample json object.
{
"id": "1",
"name": "sql",
"age": 30,
"car": "car",
"office": "office",
"cancel": "CANCEL",
"ok": "OK"
"cancel": "Anulo",
"language": "en",
"remove": "Remove",
"ignore": "Ignore",
"image_list": "Image List",
"block": "Block",
"loading": "Loading...",
"splash_screen": "Splash Screen",
"save": "Save",
"skip": "Skip",
"off": "Off",
"vibration": "Vibration",
"downloading": "Downloading...",
"fix_it": "Fix it!"
}
Like above JSON object in my JSON object have more than 500 JSON string values. How to separate single json object into two json object based on json string values?
FIRST JSON OBJECT
{
"id": "1",
"age": 30,
"office": "office"
"cancel": "Anulo",
"remove": "Remove",
"image_list": "Image List",
"loading": "Loading...",
"save": "Save",
"fix_it": "Fix it!"
}
SECOND JSON OBJECT
{
"name": "sql",
"car": "car",
"cancel": "CANCEL",
"ok": "OK"
"language": "en",
"ignore": "Ignore",
"block": "Block",
"splash_screen": "Splash Screen",
"skip": "Skip",
"off": "Off",
"vibration": "Vibration",
"downloading": "Downloading...",
}
it have a pattern? or it's just a random object?
I don't know its good way or bad.
Create Two Model class.
Class A
package com.test;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class A {
#SerializedName("id")
#Expose
private String id;
#SerializedName("age")
#Expose
private Integer age;
#SerializedName("office")
#Expose
private String office;
#SerializedName("cancel")
#Expose
private String cancel;
#SerializedName("remove")
#Expose
private String remove;
#SerializedName("image_list")
#Expose
private String imageList;
#SerializedName("loading")
#Expose
private String loading;
#SerializedName("save")
#Expose
private String save;
#SerializedName("fix_it")
#Expose
private String fixIt;
//Getter Setter for all members...
}
Class B
package com.test;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class B {
#SerializedName("name")
#Expose
private String name;
#SerializedName("car")
#Expose
private String car;
#SerializedName("cancel")
#Expose
private String cancel;
#SerializedName("ok")
#Expose
private String ok;
#SerializedName("language")
#Expose
private String language;
#SerializedName("ignore")
#Expose
private String ignore;
#SerializedName("block")
#Expose
private String block;
#SerializedName("splash_screen")
#Expose
private String splashScreen;
#SerializedName("skip")
#Expose
private String skip;
#SerializedName("off")
#Expose
private String off;
#SerializedName("vibration")
#Expose
private String vibration;
#SerializedName("downloading")
#Expose
private String downloading;
//Getter Setter for all members...
}
Now use Google GSON library to parse
Gson gson = new Gson();
String mainJson="put your main JSON here"
A a = gson.fromJson(json, A.class);
B b = gson.fromJson(json, B.class);
I'm trying to serialize to serialize the json string I have included below.
{
"mood": {
"is_featured": true,
"description": null,
"title": "2014 ",
"ordering": null,
"is_recently_modified": true,
"is_test": false,
"tracks": [
{
"album": {
"release_date": "2014-11-06",
"id": 359778,
"name": "Amansız Gücenik"
},
"name": "Hırpalandı Mayıs",
"artist": {
"id": 491169,
"name": "Ceylan Ertem"
},
"duration": 227,
"isrc": "TRA161400207",
"id": 3903997
},
{
"album": {
"release_date": "2013-08-05",
"id": 329129,
"name": "For Fuld Musik - 25 Danske Sommer Pop & Rock Hits Vol. 2"
},
"name": "Am I Wrong",
"artist": {
"id": 755957,
"name": "Nico & Vinz"
},
"duration": 387,
"isrc": "NO2G31301011",
"id": 3655085
}
],
"image_url": "some_url",
"is_recently_created": true,
"id": 128
}
}
I'm using this gson call to serialize it
Mood mood = new Gson().fromJson(result, Mood.class);
My class structers are like this.
public class Mood {
private boolean is_featured;
private boolean is_recently_modified;
private boolean is_recently_created;
private boolean is_test;
private String description;
private String title;
private String image_url;
private int id;
private int ordering;
private Track[] tracks;
public static class MoodContainer {
public Mood[] moods;
}
}
public class Track {
//variables
private Album album;
private Artist artist;
private Provider provider;
private String secure_url;
private String name;
private String region;
private String isrc;
private int duration;
private int track_order;
private int id;
}
And it goes on like this for any additional class variable. When I try to use the above call I end up with objects that have all null values. One thing to notice is some fields are not supplied in json string because different api calls supply different parts of these json strings. What I am doing wrong?
Root JSON object you provided has property mood - so you either have two options for deserialization to work properly:
Wrap your Mood class inside another object like this:
public class MoodWrapper { private Mood mood; }
and change de-serialization code to
MoodWrapper moodWrapper = new Gson().fromJson(result, MoodWrapper.class);
Skip a root object when deserializing:
final Gson gson = new Gson();
JsonParser parser = new JsonParser();
JsonObject rootObj = parser.parse(json).getAsJsonObject();
Mood mood = gson.fromJson(rootObj.getAsJsonObject("mood"), Mood.class);
The top-level elements in the JSON string should be your object's properties, not the outer element "mood" which you have.
This is my JSON:
{
"results": [
{
"user_id": "1",
"item_id": "18630",
"name": "Unnamed Item",
"price": "0",
"description": "",
"created_at": "2014-01-16 15:31:36",
"thumbnail": {
"image50": "http://www.example.com/adsa.jpg",
"image100": "hhttp://www.example.com/adsa.jpg"
},...
Am I doing the deserialization right?
public class ItemListModel {
private String user_id;
private String item_id;
private String name;
private String price;
private String category;
private ArrayList<ThumbnailResponse> thumbnail;
public ItemListModel(){}
// getters
}
public class ThumbnailResponse {
private String image50;
private String image100;
public ThumbnailResponse(){
}
//getters
}
I'm just confused, when do we use ArrayList, Array or List for array or object in the JSON file?
One more thing, do I need to make results as an array too if that's the case?
As you have given
"thumbnail": {
"image50": "http://www.example.com/adsa.jpg",
"image100": "hhttp://www.example.com/adsa.jpg"
}
is not a JsonArray. So you have no need to use ThumbnailResponse as an ArrayList into ItemListModel.
Your Model should be
public class ItemListModel {
private String user_id;
private String item_id;
private String name;
private String price;
private String category;
private ThumbnailResponse thumbnail; // Not array List
public ItemListModel(){}
// getters
}
And
One more thing, do I need to make results as an array too if that's
the case?
Your main data container should be contain ArrayList of ItemListModel. Like below
ArrayList<ItemListModel> results = new ArrayList<ItemListModel>();
[] in json -> array
{} in json -> object or map
in your case
// change
private ArrayList<ThumbnailResponse> thumbnail;
// to
private Map<String,String> thumbnail;
if you want it the way you declared your java object you need to provide a transformer (depends on the framework you are using)
List<ItemListModel > ItemListModel ;
try {
Type listType = new TypeToken<List<ItemListModel >>(){}.getType();
result= (List<ItemListModel >) gson.fromJson(result, listType);
} catch (Exception e) {
Log.e("Parsing exeption", e.getLocalizedMessage(), e);
}
this should work
I have a very long JSON to parse with Gson, but for brevity I have trimmed it to this example:
{
"volumes": [
{
"status": "available",
"managed": true,
"name": "va_85621143-1133-412f-83b4-57a01a552638_",
"support": {
"status": "supported"
},
"storage_pool": "pfm9253_pfm9254_new",
"id": "afb8e294-6188-4907-9f6f-963c7623cecb",
"size": 9
},
{
"status": "in-use",
"managed": false,
"name": "bt_newd20",
"support": {
"status": "not_supported",
"reasons": [
"This volume is not a candidate for management because it is already attached to a virtual machine. To manage this volume with PowerVC, select the virtual machine to which the volume is attached for management. The attached volume will be automatically included for management."
]
},
"storage_pool": "KVM",
"mapped_wwpns": [
"2101001B32BD4280",
"2100001B329D4280",
"2101001B32BD637E",
"2100001B329D637E"
],
"id": "c7838c79-17ca-3cbc-98e5-3567fde902d8",
"size": 0
},
{
"status": "available",
"managed": true,
"name": "vdisk138",
"support": {
"status": "supported"
},
"storage_pool": "Chassis2_IBMi",
"id": "b6d00783-9f8c-40b8-ad78-956b0299478c",
"size": 100
}
]
}
From SO and few other places, I have found that I need to define a top level container like one below but I do not know how to complete its definition
static class VolumeContainer {
//I don't know what do in here. This is the first problem
}
and then a class for each Volume
static class Volume {
private String status;
private boolean managed;
private String name;
//This is the second problem.The "support" variable should not be a string.
//It is in {}. Just for information, I won't use it.
//private String support;
private String storagePool;
private List<String> mapped_wwpns;
private String id;
private String size;
}
I am trying to parse it and this is what I coded so far:
JsonParser parser = new JsonParser();
JsonObject obj = parser.parse(response).getAsJsonObject();
Gson gson = new Gson();
The JSON string is stored in a variable named response
VolumeContainer vc = gson.fromJson(response,VolumeContainer.class);
My final requirement is a HashTable of id and associated name.
First problem: your VolumeContainer needs to be:
public class VolumeContainer {
public List<Volume> volumes;
}
it does not need to be static.
Second problem: your Volume class should be like this:
public class Volume {
private String status;
private Boolean managed;
private String name;
private Support support;
private String storage_pool;
private String id;
private int size;
private List<String> mapped_wwpns;
public String getId(){return id;}
public String getName(){return name;}
}
I defined a class named Support like this:
public class Support {
private String status;
private List<String> reasons;
}
Third problem: parsing, If response string contains your example data, simply parse like this:
Gson g = new Gson();
VolumeContainer vc = g.fromJson(response, VolumeContainer.class);
Fourth problem: get the map. Finally to get your HashMap, just do like this:
HashMap<String, String> hm = new HashMap<String,String>();
for(Volume v: vc.volumes){
hm.put(v.getId(), v.getName());
}
I am using the Kinvey Android SDK to retrieve data from their backend. It uses Gson behind the scenes. I have been unable to get it to deserialize an array of custom objects. Here is the entity definition and the JSON in question:
public class AlbumEntity extends GenericJson {
#Key("_id")
private String id;
#Key
private String name;
#Key
private String location_name;
#Key
private String start_date;
#Key("artifacts")
private Artifact[] artifacts;
static class Artifact extends GenericJson {
#Key
private String type;
#Key
private String photo_url;
public Artifact() {}
}
#Key("_kmd")
private KinveyMetaData meta;
public TripketEntity() {}
}
JSON body:
{
"_id": "5216fec12f7b521a26064f9d",
"_kmd": {
"ect": "2013-08-26T06:51:00.283Z",
"lmt": "2013-09-05T15:28:28.079Z"
},
"artifacts": [
{
"type": "photo",
"photo_url": "http://www.califliving.com/title24-energy/images/sanfrancisco.jpg"
},
{
"type": "photo",
"photo_url": "http://www.sanfrancisco.net/pictures/san-francisco.jpg"
},
{
"type": "photo",
"photo_url": "http://a2.cdn-hotels.com/images/themedcontent/en_GB/San%20Francisco_Top%2010.jpg"
},
{
"type": "photo",
"photo_url": "http://sanfranciscoforyou.com/wp-content/uploads/2010/03/san-francisco-city.jpg"
}
],
"location_name": "San Francisco",
"name": "My Trip to the Bay",
"start_date": "06/15/2013",
"owner": {
"_type": "KinveyRef",
"_collection": "user",
"_id": "5216fcd60b36c57d69000529"
},
"_acl": {
"creator": "kid_ePPs9jXc_5"
}
}
If I change the private Artifact[] artifacts object to private GenericJson[] artifacts, the array is deserialized as an array of GenericJson objects, with the data fields intact in the Unknown Fields list. How can I get it to work for my custom object?
Other things I have tried include List<Artifact> artifacts as well as ArrayList and Collection.
I'm an engineer at Kinvey working on the Android library-
Add a public modifier to the definition for the static inner class, and GSON should be able to pick it up:
...
#Key("artifacts")
private Artifact[] artifacts;
public static class Artifact extends GenericJson {
#Key
private String type;
#Key
private String photo_url;
public Artifact() {}
}
#Key("_kmd")
private KinveyMetaData meta;
...