Fill a Java Class with GSon Builder and JSon File - java

I want to fill a Java Class with an external JSon File and I works with Gson Builder. But my Java class won´t be filled by the value, which i have declared in the JSon File. What is the problem? Thanks for helping !
This is my Json File:
{
"tstamp": "2012-11-21 18:00",
"id": 123,
"publicationList": [
{
"id": "1L",
"state": "PublicationState.IMMEDIATELY",
"channel": "PublicationChannel.TIMETABLE",
"startDate": "2001-12-17 18:00",
"endDate": "2001-12-17 18:00"
},
{
"id": "2L",
"state": "PublicationState.IMMEDIATELY",
"channel": "PublicationChannel.NVS",
"startDate": "2001-12-17 18:00",
"endDate": "2001-12-17 18:00"
},
{
"id": "3L",
"state": "PublicationState.IMMEDIATELY",
"channel": "PublicationChannel.NVS",
"startDate": "2001-12-17 18:00",
"endDate": "2001-12-17 18:00"
}
]
}
This is my Gson Builder and GSon Instance Creator:
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd HH:mm")
.registerTypeAdapter(Publication.class,
new PublicationInstanceCreator()).create();
public class PublicationInstanceCreator implements
InstanceCreator<PublicationDto> {
#Override
public PublicationDto createInstance(Type type) {
return new PublicationDto();
}
}
This is the Java Class PublicattionDto:
public class PublicationDto{
private static final long serialVersionUID = 1L;
private Long id;
private PublicationState state = PublicationState.IMMEDIATELY;
private PublicationChannel channel;
private Date startDate;
private Date endDate;
//getter and setter methods
}

What is your error ? The main POJO object is also missing in your code.
Assuming this object is Publications, you only have to use
Publications p = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm").create().fromJson(json, Publications.class);
Your adapter won't work. Plus I think the IDs with 'L' won't work too (drop the L), GSon will cast the number into the correct Long type.

Related

How to load json data in java?

I'm quite new to API testing, I am wondering how to best and simple load some body?
I created simple pojo classes, but i am having problems with nested json.
ex:
{
"listOfItems": [
{
"name": "name1",
"value": "Jack"
},
{
"name": "nameDate",
"value": "20-08-2021-08-00-00"
},
{
"name": "address",
"value": "address here",
}
{
"name": "name2",
"value": "Smith"
}
],
"something": [],
"size": 1
}
Then, in classes I used:
ClassName {
private List<ListOfItems> listOfItems;
private List<something> something;
private int size;
//setters and getters
}
and
Class ListOfItems{
private String name;
private String value;
//getters and setters
}
then in test class I am trying to use it, but have no idea how.
public Class Test {
ClassName className = new ClassName();
ListOfItems list = new ListOfItems();
//how to get list with 3x name and 3x value like in json?
className.setsize(150);
given().when().body(???).post("\endpoint").then()...
}
But I have no idea how to declare those 4 properties (name, value)
You are actually on a pretty good track, you can use Gson library to help you out, Here is the video example for your explanation which I used to learn Gson back when I needed it

Write java class with nested Map to custom json format using Gson

What Java data structure can be used to serialize to the following Json which have a set of child objects?
Example:
{
"John": {
"Type": "Person",
"age": 30,
"Sean": {
"Type": "child",
"age": 3
},
"Julian": {
"Type": "child",
"age": 4
}
},
"Paul": {
"Type": "Person",
"age": 64,
"Stella": {
"Type": "child",
"age": 10
},
"James": {
"Type": "child",
"age": 12
}
}
}
Writing John and Paul can be done by: Map<String,Person> but i cannot figure out how to nest the Child without having the 'children' property.
Example:
{
"John": {
"Type": "Person",
"age": 30,
"children": {
"Sean": {
"Type": "child",
"age": 3
},
"Julian": {
"Type": "child",
"age": 4
}
}
}
}
I am not sure it is relevant, but Gson is being used to create the Json file
I'm not sure wheher this is possible with GSON though it's possible with Jackson.
With GSON you can try custom JsonSerializer, which might look something like this:
private static class PersonTypeSerializer implements JsonSerializer<Person> {
#Override
public JsonElement serialize(Person person, Type type, JsonSerializationContext jsonSerializationContext) {
JsonObject personJson = personToJson(person);
for (Map.Entry<String, Person> child : person.getChildren().entrySet()) {
personJson.add(child.getKey(), personToJson(child.getValue()));
}
return personJson;
}
private static JsonObject personToJson(Person person) {
JsonObject personJson = new JsonObject();
personJson.addProperty("Type", person.getType());
personJson.addProperty("age", person.getAge());
return personJson;
}
}
and register to GSON instance like this:
Gson gson = new GsonBuilder().registerTypeAdapter(Person.class, new PersonTypeSerializer())
.create();
Note that code assumes that both type "Person" and "child" are represented by the same Person class. It should be pretty easy to modify this if not.

How to deserialize a JSON file ( using Google JSON) consisting of same key name but uses different type?

Consider the following JSON File:
{
"version": "1.0",
"firstData": {
"meta": "this is string",
"version": "1"
},
"SecondData": {
"meta": ["string1", "string2", "string3"],
"version": "1"
},
"ThirdData": {
"meta": true,
"version": "1"
},
"FourthData": {
"meta": [true, false, false, true],
"version": "1"
},
"FifthData": {
"meta": [{
"meta": "string",
"version": "2"
},
{
"meta": ["string1","string2"],
"version": "2"
}]
"version": "1"
}
}
As seen, The "meta" attribute has different data type, sometimes it is String, sometimes it is ArrayOfString, sometimes Boolean etc.
Since my JSON file has several data,
I want it to follow the following Structure :
class information
{
String version;
HashMap<String,Data> details;
}
class Data
{
variable meta;
String version;
}
How do I create a corresponding POJO and deserialize it using Google GSON?
Just define your meta as JsonElement. Then you will have sort methods like: getAsString, getAsBoolean, getAsJsonObject, getAsJsonArray, ..., and also you are able to deserialize it again after you find out what is the type.
So your class could look like:
public class SomeClass {
private int version;
private JsonElement meta;
//getters and setters and other stuff
}
Edit: More elaboration and implementation
Define two classes: GeneralItem and GeneralData
class GeneralItem
{
public final int version;
public final JsonElement meta;
}
class GeneralData
{
public final String version;
public final Map<String, GeneralItem> items;
public GeneralData(String version, Map<String, GeneralItem> items)
{
this.version = version;
this.items = items;
}
}
And then we define a custom deserializer for our GeneralData:
class GeneralDataDeserializer implements JsonDeserializer<GeneralData>
{
#Override
public GeneralData deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
{
final JsonObject object = json.getAsJsonObject();
final String version = object.get("version").getAsString();
object.remove("version");
HashMap<String, GeneralItem> items = new HashMap<>(object.size());
for (Map.Entry<String, JsonElement> item : object.entrySet())
items.put(item.getKey(), context.deserialize(item.getValue(), GeneralItem.class));
return new GeneralData(version, items);
}
}
Finally registering the deserializer to our gson instance and getting the data:
final Gson gson = new GsonBuilder()
.registerTypeAdapter(GeneralData.class, new GeneralDataDeserializer())
.create();
final String json = "your json here";
final GeneralData data = gson.fromJson(json, GeneralData.class);
System.out.println(data.items.get("firstData").meta.getAsString());
//other parts you want
(Note that constructors, getter and setters, error checking, etc. are removed for the sake of brevity)

Howto configure which POJO fields to serialize to JSON with GSON?

I have a List of Objects with multiple fields. Based on the API call, the List would be returned with only a specific set of fields. When I use transient - it does not serialize that particular field. But, that field should be returned for another API call. I am using Gson.
In the example below, based on the API, I wanted to print a list of Table instances with only E.g. "name" of the Table instances, or both "name" and "location", or just location. There could be 30 fields in the Table Object.
One way is to map it to a POJO for each scenario and then print it out. Is there a better way to do this? where you can select/choose/constrain which field gets serialized.
E.g.
package Testing;
import java.util.ArrayList;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class TestJson {
public static Gson obGson = new GsonBuilder().setPrettyPrinting().create();
public static void main(String[] args) {
ArrayList<Table> myTable = new ArrayList<Table>();
myTable.add(new Table("John", "Chicago"));
myTable.add(new Table("David", "Seattle"));
myTable.add(new Table("June", "Dallas"));
System.out.println(obGson.toJson(myTable));
}
}
class Table {
String name;
String location;
public Table (String _name, String _location) {
name = _name;
location = _location;
}
}
The output for the above looks like this. When API-1 is called then the output should like below.
[
{
"name": "John",
"location": "Chicago"
},
{
"name": "David",
"location": "Seattle"
},
{
"name": "June",
"location": "Dallas"
}
]
But when API-2 is called then the output should like below. Only return the fields that are approved for that API call.
[
{
"name": "John"
},
{
"name": "David"
},
{
"name": "June"
}
]
Similarly, the return could be managed based on the API call.
Implement ExclusionStrategy like
#RequiredArgsConstructor
public class FieldExclusionStrategy implements ExclusionStrategy {
#NonNull
private final Collection<String> serializedFields;
#Override
public boolean shouldSkipField(FieldAttributes f) {
if(serializedFields.contains(f.getName())) return false;
return true;
}
#Override
public boolean shouldSkipClass(Class<?> clazz) { return false; }
}
Use like
#Test
public void testShouldSkipField() {
Gson gson;
Table table = new Table();
Collection<String> serializedFields = new ArrayList<>();
ArrayList<Table> myTable = new ArrayList<Table>();
myTable.add(new Table("John", "Chicago"));
myTable.add(new Table("David", "Seattle"));
myTable.add(new Table("June", "Dallas"));
serializedFields.add("name");
gson = new GsonBuilder()
.setPrettyPrinting()
.addSerializationExclusionStrategy(
new FieldExclusionStrategy(serializedFields))
.create();
log.info("\n{}", gson.toJson(myTable));
serializedFields.add("location");
gson = new GsonBuilder()
.setPrettyPrinting()
.addSerializationExclusionStrategy(
new FieldExclusionStrategy(serializedFields))
.create();
log.error("\n{}", gson.toJson(myTable));
serializedFields.remove("name");
gson = new GsonBuilder()
.setPrettyPrinting()
.addSerializationExclusionStrategy(
new FieldExclusionStrategy(serializedFields))
.create();
log.error("\n{}", gson.toJson(myTable));
}
Above would log something like
2017-12-23 19:47:17.028 INFO org.example.gson.FieldExclusionStrategyTest:37 -
[
{
"name": "John"
},
{
"name": "David"
},
{
"name": "June"
}
]
2017-12-23 19:47:17.034 ERROR org.example.gson.FieldExclusionStrategyTest:44 -
[
{
"name": "John",
"location": "Chicago"
},
{
"name": "David",
"location": "Seattle"
},
{
"name": "June",
"location": "Dallas"
}
]
2017-12-23 19:47:17.035 ERROR org.example.gson.FieldExclusionStrategyTest:51 -
[
{
"location": "Chicago"
},
{
"location": "Seattle"
},
{
"location": "Dallas"
}
]
You need to build GSON again after changing list of serialized field names.
GSON caches internally the result - true|false - upon first call for some field name and does not query it again for cached field name.
And to add ExclusionStrategy you need to build GSON with GsonBuilder which then registers ExclusionStrategy (or many of them).
See also my question about this topic.

Gson: handling an optional List [duplicate]

This question already has an answer here:
Parsing JSON with GSON, object sometimes contains list sometimes contains object
(1 answer)
Closed 6 years ago.
I am using Gson to parse JSON (generated by the jquery query builder) to a corresponding Java Object. My issue is that the attribute "value" can be either an array or a single value:
{
"condition": "AND",
"rules": [
{
"id": "date",
"field": "date",
"type": "date",
"input": "text",
"operator": "between",
"value": [
"01.01.2016",
"20.01.2016"
]
}
]
}
or
{
"condition": "AND",
"rules": [
{
"id": "date",
"field": "date",
"type": "date",
"input": "text",
"operator": "equal",
"value": "01.01.2016"
}
]
}
Apparently Gson can build the object for the first JSON if my class has a field like private String[] value and for the second, a field like private String value — but not both JSON inputs with either Java field option.
So my question: Is the a way to handle both, either a single "value" or an array of "values"?
I don't know what is the structure of a class that you are using to deserialize this JSON, but I'd like to sugest that there is a class like this
public class Rule {
private String id;
private String field;
private String type;
private String input;
private String operator;
private List<String> value;
// constructors, getters and setters
}
As you can see the value property is defined as a list of java.lang.String objects. This approach will help us to handle both cases: when value is an array and when it's a simple string value.
What can we do with the Gson? We can create custom deserializer like this
public class CustomSerializer implements JsonDeserializer<Rule> {
public Rule deserialize(JsonElement jsonElement, Type type,
JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
JsonObject obj = (JsonObject) jsonElement;
JsonElement value = obj.get("value");
List<String> values = new ArrayList();
if (value.isJsonArray()) {
for (JsonElement jsonElement1 : value.getAsJsonArray()) {
String str = jsonElement1.getAsString();
values.add(str);
}
} else {
values.add(value.getAsString());
}
// deserialize other properties
Rule rule = new Rule();
rule.setValue(values);
// set other properties
return rule;
}
}
After that you need to register deserializer with
Gson gson = new GsonBuilder()
.registerTypeAdapter(Rule.class, new CustomSerializer ())
.create();
and you can deserialize JSON object like
{
"id": "date",
"field": "date",
"type": "date",
"input": "text",
"operator": "equal",
"value": "01.01.2016"
}
that is a part of your whole data structure.

Categories

Resources