GsonFromJson: how to serialize and de serialize with array structures - java

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();
}

Related

How to loop trough nested JSON and get value using Java, SpringBoot

I have a nested JSON that I want to loop through and get value based on key.
Data.json
{
"car": [
{
"date": 1324599600000,
"values": [
{
"name": "Audi",
"price": "11212.12"
},
{
"name": "Bmw",
"price": "22321.3"
},
{
"name": "Cittroen",
"price": "23432.2"
},
{
"name": "Tuareg",
"price": "556456.3"
}
]
}
I created 3 object models based on JSON data.
CarResponse.java
public class CarResponse {
#JsonProperty(value = "car")
List<Car> cars;
//getters,setters
Car.java
public class Car{
#JsonProperty("values")
private List<CarValue> carValue;
//getters, setters
CarValue.java
public class CarValue {
private String name;
private BigDecimal price;
//getters, setters
DataParse.java
public class DataParse{
CarResponse response;
public CarValue parse(){
CarValue carValue = new CarValue();
//NEED HELP WITH THIS PART
for(Car cars : response.getQuote()){
for(CarValue qv : cars.getCarValue()){
String type = qv.get("name").asText();
Decimal value = qv.get("price").decimalValue();
carValue.setName(qv.getName());
carValue.setPrice(qv.getPrice());
}
}
return quoteValue;
}
}
In JSON I need to check if car name is Audi and if car name is Tuareg then save it and display it.
Nested for loop part of code is not working
for(Car cars : response.getQuote()){
for(CarValue qv : cars.getCarValue()){
String type = qv.get("name").asText();
Decimal value = qv.get("price").decimalValue();
carValue.setName(qv.getName());
carValue.setPrice(qv.getPrice());
}
}
Just put it as an example of what I need to do in this step which is check for key in JSON and if it is that key with for example name = Audi then
carValue.setName(qv.getName());
With my code above I am getting this in the console.
carValue=[carValue{name=null, price=null}
Assuming that your deserialization is working correctly, you should change the part that "is not working" to:
String type = qv.getName();
BigDecimal value = qv.getPrice();
If for some reason you want to use this qv.get(key) method, you should post its implementation.
When getName and getPrice are still returning null, it means you have a problem with the deserialization, for example a wrong setter method name. Still, without the implementation is impossible to understand.
Here is the official documentation of Jackson, the library used by default with spring-boot for JSON serialization / deserialization.
And here is Spring blog post about it.

Realm : Store JsonArray as String field of CustomObject

I have an object like above one, but instead of String array, it is like jsonArray. I want to store that as a string to the realm. Have a look at below JSON structure for same.
{
"id": "aadessddsdss9bdfs69c-6f13-4417-b356-230dbb36c887",
"propertyId": "49bbe89e-8709-4e0f-a680-3c73aa36e424",
"rowId": "zzzadsaaedsd3fsdfsss33a-11fc-4396-8c69-d88001e813c5",
"jobFormsId": "",
"observation": [
{
"FieldId": "ddbaesds33fsdf13a-11fc-4396-8c69-d88001e813c5",
"Value": "sfshello"
},
{
"FieldId": "e88dddfssdc4s7c4-73bc-45ba-900f-bf5286036003",
"Value": "ritika"
},
{
"FieldId": "b2ea8sdsdsfssdc144-812d-47a2-9239-8471558df189",
"Value": "May"
}
]
}
I have made Class to store above json structure to realm (Here I want to store observations as String to realm)
AdditionalData.java
public class AdditionalData extends RealmObject {
#PrimaryKey
private String id;
private String jobFormId;
private String propertyId;
private String observations;
private String rowId;
public AdditionalData() {
// Empty constructor
}
}
Now, When am storing observations as a string to realm the format of that is getting changed. What is the proper way to store observations as a string to the realm.
Update:
I know that, to store observations, I need to make separate class for that. But the data in Observations can be anything. That's why I want to store that as String only.

How to Parse Nested / Multiple Json Objects using Retrofit

The JSON I'm parsing looks like this:
{ "version": 1
"data": {
"1001": {
"id": 1001,
"name": "herp",
"into": [
"3111": "we"
]
},
"1032": {
"id": 1002,
"name": "derp",
"into": [
"36": "w",
"12341: "c"
],
"tags": [
"hi there"
],
"cost" {
"even": 15
}
},
"1603": {
"id": 1003,
"name": "her",
"into": [
"37": "dll",
"58": "eow",
"32145": "3a"
],
"cost" {
"highest": 325
"lowest": 100
}
},
.... Even more data
}
The Json that is within "data" goes on for a while and does not have a set endpoint. I have no control over the Json, I'm just trying to read it. Unfortunately, with my class code I'm unable to get it to work. When I make a retrofit call the information inside "data" is empty.
I've tried many iterations of implementing this, including using a deserializer and restructuring my POJO code. This is the current state of my Data class:
public class Data {
private Map<String, Item> itemData;
// Relevant Getters, Setters and Constructors //
}
For my Item Class, the main issue is that the JSON Content isn't set, it can vary at times. As you can see above the values inside "into" vary and sometimes the amount of things within item changes as well such as "tags" or "cost":
public class Item {
private int id;
private String name;
private String group;
private String description;
private Map<String, String> into;
private List<String> tags;
private Map<String, Integer> cost;
// Relevant Getters, Setters and Constructors //
When I use this code my data class is empty, I don't see any errors in the log so I can't seem to figure out why the GSON isn't working with this.
In case you wanted to see how I construct my RestClient, here it is:
RestAdapter.Builder builder = new RestAdapter.Builder()
.setEndpoint(ROOT)
.setClient(new OkClient(new OkHttpClient()))
.setLogLevel(RestAdapter.LogLevel.FULL);
RestAdapter restAdapter = builder.build();
REST_CLIENT = restAdapter.create(DataApi.class);
I know that my Rest Query works because I can get the content within "version" but everything inside data is null.
I am officially a dumb scrub and completely looked over the easiest possible fix and should have my account and developer title revoked.
This is all I should have done:
public class ItemGroup {
private String version;
private Map<String,Item> data;
//...Man i'm so dumb...
}
AS REFERENCE FOR THE FUTURE. The reason why this works is because the JSON is in this format { { } { } { } }. Which means you have 3 objects of objects, as opposed to { [ ] [ ] [ ] } which is 3 objects of a list. What I had done was treat { { } { } { } } as { { { } { } { } } }. Which is not correct. By using a map which is basically a collection of pairs, we are able to imitate the { { } { } { } } with a Map.
Map Object { {Key-Pair Object} {Key-Pair Object} {Key-Pair Object} }
Just a quick idea for your Pojos:
Not sure if this will work. Maybe write a custom deserializer.
public class YourResponse {
int version;
Data data;
class Data {
Subdata subData;
}
class Subdata {
private int id;
private String name;
private ArrayList<Into> into;
private ArrayList<String> tags;
//...
}
class Into {
// "3111": "we"
private String into;
}
}

Deserializing inner class with gson returns null

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.

How to convert Json String with dynamic fields to Object?

I have the followed snipets of Json String:
{
"networks": {
"tech11": {
"id": "1",
"name": "IDEN"
},
"tech12": {
"id": "2",
"name": "EVDO_B"
}
}
}
I use some methods to convert this String to Object:
private static Gson mGson = new Gson();
...
public static WebObjectResponse convertJsonToObject(String jsonString) {
WebObjectResponse webObjectResponse = null;
if(jsonString != null && jsonString.length() > 1){
webObjectResponse = mGson.fromJson(jsonString, WebObjectResponse.class);
}
return webObjectResponse;
}
Where WebObjectResponse is class that should represent above mentioned String.
Its not complicated if I get static fields.
But in my case the values have different names: tech11, tech12 ....
I can use #SerializedName but its works in specific cases like convert "class" to "class_".
As you see networks Object defined as list of tech Objects but with different post-fix.
public class WebObjectResponse{
private DataInfoList networks = null;
}
This is static implementation, i defined 2 values tech11 and tech12 but next response might be techXX
public class DataInfoList {
private DataInfo tech11 = null;
private DataInfo tech12 = null;
}
public class DataInfo {
private String id = null;
private String name = null;
}
What is the good way to convert current Json String to Object where list of elements are Objects too and have different names?
Thank you.
Use a Map!
I would do the following
public class WebObjectResponse {
private Map<String, DataInfo> networks;
}
public class DataInfo {
private String id = null;
private String name = null;
}
// later
Gson gson = new Gson();
String json = "{\"networks\": {\"tech11\": { \"id\": \"1\",\"name\": \"IDEN\" }, \"tech12\": { \"id\": \"2\", \"name\": \"EVDO_B\" } }}";
WebObjectResponse response = gson.fromJson(json, WebObjectResponse .class);
For each object in json networks, a new entry will be added to the Map field of your class WebObjectResponse. You then reference them by techXX or iterate through the keyset.
Assuming a structure like this
{
"networks": {
"tech11": {
"id": "1",
"name": "IDEN"
},
"tech12": {
"id": "2",
"name": "EVDO_B"
},
"tech13": {
"id": "3",
"name": "WOHOO"
}, ...
}
}
We would need your class structure for more details.
As far as I am aware, I think you will need to have some mappings defined somewhere (I used xml's) and then try to match json with one of the mappings to create objects.
Google gson is good. I did it in Jackson
Also, converting objects should be trivial. But since you might have variable fields like tech11 and tech12 , you might want to store the "network" value as a string and then extract fields out of it when required.
Hope I could help.
Edit : Sotirious nails it.
Please use this link for converting SON Response to Java POJO class
http://www.jsonschema2pojo.org/

Categories

Resources