I want to use Gson to Deserialize my JSON into objects.
I've defined the appropriate classes, and some of those class' objects are included in other objects.
When trying to deserialize the whole JSON, I got null values, so I started breaking it apart.
I reached the point where all lower classes stand by them selves, but when trying to deserialize into an object that holds an instance of that smaller object - every thing returns as null.
My partial JSON:
{
"user_profile": {
"pk": 1,
"model": "vcb.userprofile",
"fields": {
"photo": "images/users/Screen_Shot_2013-03-18_at_5.24.13_PM.png",
"facebook_url": "https://google.com/facebook",
"site_name": "simple food",
"user": {
"pk": 1,
"model": "auth.user",
"fields": {
"first_name": "blue",
"last_name": "bla"
}
},
"site_url": "https://google.com/"
}
}
}
UserProfile Class:
public class UserProfile {
private int pk;
private String model;
private UPfields fields = new UPfields();//i tried with and without the "new"
}
UPfields Class:
public class UPfields {
private String photo;
private String facebook_url;
private String site_name;
private User user;
private String site_url;
}
User Class:
public class User {
private int pk;
private String model;
private Ufields fields;
}
Ufields Class:
public class Ufields {
private String first_name;
private String last_name;
}
In my main I call:
Gson gson = new Gson();
UserProfile temp = gson.fromJson(json, UserProfile.class);
So my temp object contain only null values.
I've tried changing the classes to static, and it doesn't work.
The UPfields object and all lower one work fine.
Any suggestions?
when I remove the
"{
"user_profile":"
and it's closing bracket, the deserialize to a user_profile object works.
In order to parse this json example you have to create auxiliary class, which will contain field named user_profile of type UserProfile:
public class UserProfileWrapper {
private UserProfile user_profile;
}
and parse this json string with this class:
UserProfileWrapper temp = gson.fromJson(json, UserProfileWrapper.class);
Gson starts by parsing the outermost object, which in your case has a single field, user_profile. Your UserProfile class doesn't have a user_profile field, so it can't deserialize it as an instance of that class. You should try to deserialize the value of the user_profile field instead.
Related
I am having below 2 JSON, one for login and another one for order
{
"head": {
"requestCode": "code"
},
"body": {
"reqId": "xyz",
"userName": "xyz",
"passwd": "xyz",
}
}
{
"head": {
"requestCode": "code"
},
"body": {
"reqId": "xyz",
"orderId": "xyz"
}
}
I am trying to write java pojo where the head and refId of body are common for each json but other content of body.
something like the below pojo. Now problem is GSon cannot parse and build objects based on nested parameterized types. Is there any better way to implement it? Not JSON structure will not change.
POJO
public class Base<T extends Body> {
#SerializedName("head")
#Expose
public Head head;
#SerializedName("body")
#Expose
private T body;
}
public class Body {
#SerializedName("clientCode")
#Expose
private String clientCode;
}
public class Head {
#SerializedName("requestCode")
#Expose
public String requestCode;
}
public class Login extends Body {
#SerializedName("userName")
#Expose
public String userName;
#SerializedName("passwd")
#Expose
public String passed;
}
public class Order extends Body {
#SerializedName("orderId")
#Expose
String orderId;
}
You could either introduce two new subclasses of Base which you use for deserialization, for example:
class LoginRequest extends Base<Login> { }
class OrderRequest extends Base<Order> { }
Or you can use Gson's TypeToken class to deserialize a parameterized Base type. See also the corresponding section in the user guide. For example:
Type loginType = new TypeToken<Base<Login>>() {}.getType();
Base<Login> loginRequest = gson.fromJson(..., loginType);
Im working on a project where we used jsonfile as its database since SQLite doesnt meet the requirement. The project has a portion when an object fron the wordbank is use it will change the status(such as 1-4). I made use of JSONArray to access the data. When i tried to change/edit the status, it doesnt save or write back to the jsonfile. Instead it only works on the momentary use of the application.
From searches, alot of stuff pop out that using gson. I concluded to use gson.
I am new to gson and just started learning it the other day. And i am having troubles with it.
This is the structure of my jsonfile. It has 2 objects(users and wordbank) that are arrayed
{
"users" :
[{
"username": "free",
"password": "free",
"email": "free#gmail.com",
"type": "1"
},
{
"username": "premium",
"password": "premium",
"email": "premium#gmail.com",
"type": "2"
}],
"wordbank" :
[{
"English": "able",
"Cebuano": "kaya",
"Pronunciation": "ká-ya",
"POS": "adjective",
"Audio": "kaya.mp3",
"Status": "0"
},
{
"English": "advice",
"Cebuano": "tambag",
"Pronunciation": "tam-bag",
"POS": "noun",
"Audio": "tambag.mp3",
"Status": "0"
}]
}
From what I've seen in tutorial videos is that you create a different java class for its model. So i create 3 java class. user, wordbank and dictionary (combining them both).
public class dictionary{
users[] user;
wordbanks[] word;
}
Im using an existing jsonfile already so i parsed it and got its jsonstring. After which i tried to deserialize it using
jsonstring = readFromFile();//returns string from jsonfile
dictionary list = new Gson().fromJson(jsonstring, dictionary.class);
runned it and debug it. but when i got the results. it was null.
QUESTIONS:
1.Will I be able to edit and save the changes in json file by using gson?
2.Is my structure correct for the distionary class?
3.how to serialize and deserialize it?
If your member variables of pojo Classes(users,workdbank,dictionary) don't match with JSON key, consider using #SerializedName provided by GSON. In your case, i was able to deserialise the string using gson by using #SerializedName as shown below
User Class
public class User {
#SerializedName("username")
private String userName;
#SerializedName("password")
private String password;
#SerializedName("email")
private String email;
#SerializedName("type")
private String type;
// Add Getters and Setters
}
WordBank Class
public class Wordbank {
#SerializedName("English")
private String english;
#SerializedName("Cebuano")
private String cebuano;
#SerializedName("Pronunciation")
private String pronunciation;
#SerializedName("POS")
private String pos;
#SerializedName("Audio")
private String audio;
#SerializedName("Status")
private String status;
// Add getters and Setters
}
Dictionary Class
public class Dictonary {
#SerializedName("users")
User[] userArray;
#SerializedName("wordbank")
Wordbank[] wordbankArray;
public User[] getUserArray() {
return userArray;
}
public void setUserArray(User[] userArray) {
this.userArray = userArray;
}
public Wordbank[] getWordbankArray() {
return wordbankArray;
}
public void setWordbankArray(Wordbank[] wordbankArray) {
this.wordbankArray = wordbankArray;
}
}
After making necessary changes as explained above, I was able to deserialise the string
Dictonary dictonary = new Gson().fromJson(input,Dictonary.class);
Yes you can use Gson for all your requirements. First create matching Pojo for your json structure. you can use tools such as this pojo generator. Just paste the json there (don't select json schema) and generate. Assuming you have three classes Result (contains to lists, similar to your dictionary class), User and Wordbank class. You can read (deserialize) and write (serialize) back into a file as follows.
try {
// deserialize
Result result = gson.fromJson(new FileReader(new File("src/test/resources/sample.json")), Result.class);
// ... update result as required
// result.users.remove(0);
// serialize
String json = gson.toJson(result);
Files.write(new File("src/test/resources/sample.json").toPath(), json.getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
I have a Java EE project that is using GSON library (Google's library for processing of JSON objects).
In my entity classes I use #Expose annotation to control which fields are considered by GSON. I also use serialize/deserialize properties on that annotation to control which fields are considered when serializing a Java object to JSON and which fields are considered when deserializing JSON objects to Java objects. For example:
public class Movie {
#Expose(serialize=true, deserialize=false)
#Id
#GeneratedValue
private long id;
#Expose(serialize=true, deserialize=true)
private String name;
#Expose(serialize=true, deserialize=true)
private String genre;
#Expose(serialize=false, deserialize=true)
private String secretID;
}
Here when I send the JSON object to be deserialized into Java object I send an object like this:
{
"name": "Memento",
"genre": "thriller",
"secretID": "123asd"
}
And, when I serialize Java object to JSON I get something like this:
{
"id": 1,
"name": "Memento",
"genre": "thriller"
}
I have this Java code:
public static void main(String[] args) {
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().setPrettyPrinting().create();
String json = gson.toJson(new Movie());
System.out.println(json);
}
that generates this as it's output:
{
"id": 0,
"name": "",
"genre": ""
}
Those are fields that are marked to be serialized. However, what if I need to print out all of the fields that are marked to be deserialized, so that I can easier create a JSON object that will be used as input when creating new Movies.
The desired output is this:
{
"name": "",
"genre": "",
"secretID": ""
}
Note: I don't want to change serialize/deserialize properties on #Expose annotations because they are set to how my application needs to work. I just need an easy way to generate a template JSON objects that will be used as input to my application, so I don't have to type it manually.
You could implement more generic ExclusionStrategy like:
#RequiredArgsConstructor
public class IncludeListedFields implements ExclusionStrategy {
#NonNull
private Set<String> fieldsToInclude;
#Override
public boolean shouldSkipField(FieldAttributes f) {
return ! fieldsToInclude.contains(f.getName());
}
#Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
}
then use it like:
Set<String> fieldsToInclude =
new HashSet<>(Arrays.asList("name", "genre", "secretID"));
ExclusionStrategy es = new IncludeListedFields(fieldsToInclude);
Gson gson = new GsonBuilder().setPrettyPrinting().serializeNulls()
.addSerializationExclusionStrategy(es).create();
Note following things:
You should not now use the builder method .excludeFieldsWithoutExposeAnnotation.
By default Gson does not serialize fileds with null values so you need to use builder method .serializeNulls(). This does not generate Json with string values "" but just null.
In your example Json fields contained empty strings as values but you did not introduce default constructor Movie() that would initialize field values to empty strings so they remain null. But if you initialize them - say to empty string ""- then they are not null & you do not need to use builder method .serializeNulls().
BUT if you really need and want only to serialize based on #Expose(deserialize=true) then the ExclusionStrategy can be just:
public class PrintDeserializeTrue implements ExclusionStrategy {
#Override
public boolean shouldSkipField(FieldAttributes f) {
Expose annotationExpose = f.getAnnotation(Expose.class);
if(null != annotationExpose) {
if(annotationExpose.deserialize())
return false;
}
return true;
}
#Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
}
I am building json for highchart using gson api.
"series": [
{
"name": "tesT",
"data": [["1",12345678], ["2",4534534], ["3",2345678], ["4",456345], ["5",342342]]
}
]
My pojo class is
public class Series {
private String name;
private List<Data> data; // Not working
// getters and setters
}
public class Data {
private String name;
private Double value;
// getters and setters
}
I am getting the output for data like [[name: "1", value: 12345678],[name: "2", value: 4534534]...].
Expected output is [["1",12345678], ["2",4534534]....].
What datatype i should use for the data attribute in the Series class?
Declare a class with a String and a double as data type and define the your list as a holder of that class.
I.e.
public class MyData {
private String nameString;
private Double myDouble;
....
....
}
And in the class Series:
private List<MyData> data;
....
Answer is two dimensional array.
Since i am having two different datatypes inside the two dimensional array i have used Object[][]
public class Series {
private String name;
private Object[][] data;
// getter and setter
}
It works like a charm!!!!!!!!!
We have this Json:
{
"id": 500,
"field1": "TESTE",
"banco": {
"id": 300,
"descricao": "BANCO_TESTE"
},
"categorias": [
{
"id": 300,
"descricao": "PT",
"publica": true
}
]
}
And my beans:
public class Asking implements Serializable {
private long id;
private String field1;
private Bank bank;
private List<Categoria> categorias;
//[getters and setters]
}
The beans Bank and Categoria:
public class Bank implements Serializable {
private Long code;
private Long id;
private String descricao;
//getters and setters
}
public class Categoria implements Serializable {
private Long code;
private Long id;
private String descricao;
private boolean marcada;
private boolean publica;
//getters and setters
}
When I call:
gson.fromJson(strJson, tokenType);
The error appears:
Method threw 'java.lang.StackOverflowError' exception.
What is wrong?
I can't reproduce this problem. One of two things are wrong here:
Your beans are not defined as you say they are. Check to see if they have other fields hidden within the getter and setter method section. This can happen if you have a circular reference.
You've stated in the comments that this is likely to be your problem. I recommend:
Remove the extra fields from your bean
Create a new class that contains the extra fields, and a field for the Asking instance
Deserialize the Asking instance using Gson, and then pass it into the new class's constructor.
You are doing something unexpected with your setup of the gson.fromJson method. Here's what I'm using that works great:
public static void parseJSON(String jsonString) {
Gson gsonParser = new Gson();
Type collectionType = new TypeToken<Asking>(){}.getType();
Asking gsonResponse = gsonParser.fromJson(jsonString, collectionType);
System.out.println(gsonResponse);
}
Either check your bean class definitions for extra fields, or, failing that, try to make your deserialization match mine.