Using Gson with multiple values for object - java

I have this Json code:
{
"term" : {
"PrincipalTranslations" : {
"0" : {
termine:"casa",
traduzione:"home"
}
"1" :{
termine:"testa",
traduzione:"head"
}
"2" :{
termine:"dito",
traduzione:"finger"
}
}
}
}
How can I deserialize the object 0, 1, 2??
If instead of object 0, 1, 2 I wrote object "zero" (and stop), it works!
I've used this implementation:
public class Item {
private term term;
public term getTERM() {
return term;
}
}
public class term {
private PrincipalTranslations PrincipalTranslations;
public PrincipalTranslations getPrincipalTranslations() {
return PrincipalTranslations;
}
}
public class PrincipalTranslations {
private zero zero;
public zero getZero() {
return zero;
}
}
public class zero {
private String termine;
public String gettermine() {
return termine;
}
}
and use it so, it print (in the right way) "casa"
public class MainClass {
public static void main(String[] args) throws IOException {
FileReader reader = new FileReader("/home/peppe/test_ff");
Gson gson = new GsonBuilder().create();
Item p = gson.fromJson(reader, Item.class);
System.out.print(p.getTERM().getPrincipalTranslations().getZero().gettermine());
reader.close();
}
}

If you want to call the object zero, than in your ’Principal Translations‘ class use the ’SerializedName’ annotation: http://google-gson.googlecode.com/svn/tags/1.2.3/docs/javadocs/com/google/gson/annotations/SerializedName.html
It will look like this:
#SerializedName("0")
public Zero zero;

Related

Getting nested array from JSON using Jackson lib - Java

I've got a JSON like this:
{
"result": [
{
"reservation_id": 101,
"euro_fee": 11.00,
"hotel_id": 1
},
{
"reservation_id": 102,
"euro_fee": 12.00,
"hotel_id": 2
},
{
"reservation_id": 103,
"euro_fee": 13.00,
"hotel_id": 3
}
],
"meta": {
"ruid": "0001="
}
}
and I'm trying to use Jackson (with Spring Boot) for parse and bind it. Here is my POJO's:
Response.java
public class Response {
private Result result;
private Meta meta;
public Response() {
}
public Result getResult() {
return result;
}
public void setResult(Result result) {
this.result = result;
}
public Meta getMeta() {
return meta;
}
public void setMeta(Meta meta) {
this.meta = meta;
}
}
Meta.java
public class Meta {
private String ruid;
public Meta() {
}
public String getRuid() {
return ruid;
}
public void setRuid(String ruid) {
this.ruid = ruid;
}
}
Result.java
public class Result {
private Booking[] results;
public Result() {
}
public Booking[] getResults() {
return results;
}
public void setResult(Booking[] results) {
this.results = results;
}
}
Booking.java
public class Booking {
private long reservation_id;
private long hotel_id;
private Double euro_fee;
public Booking() {
}
public long getReservation_id() {
return reservation_id;
}
public void setReservation_id(long reservation_id) {
this.reservation_id = reservation_id;
}
public long getHotel_id() {
return hotel_id;
}
public void setHotel_id(long hotel_id) {
this.hotel_id = hotel_id;
}
public Double getEuro_fee() {
return euro_fee;
}
public void setEuro_fee(Double euro_fee) {
this.euro_fee = euro_fee;
}
}
I can get ruid from meta using:
// getting JSON from REST
String response = restTemplate.postForObject(resourceURL, httpEntity, String.class);
// use jackson
ObjectMapper mapper = new ObjectMapper();
Response theResponse = mapper.readValue(response, Response.class);
System.out.println("getRuid: " + theResponse.getMeta().getRuid());
but I can't get objects or single item from nested array. When I'm trying to get array of items I'm getting error:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of out of START_ARRAY token at [Source: (String)...
I know this one should be easy, but I'm using Jackson for the first time and the problem might be somewhere in the deep.
Change your Response class.
Try with this:
public class Response {
private List<Booking> result;
private Meta meta;
//getter setter
}

GSON Double Rounding when adding in HashSet

So I am parsing a VERY large JSON file with the use of GSON.
The class I'm parsing it into is structure like this:
What I'm trying to do is round the doubles (in the HashSet, in the Geometry class) up to to 4 decimal points. So as doubles are being added to the HashSet, I want to round them up.
public class Contours {
public String name = null;
public String type = null;
ArrayList<Features> features = null;
class Features {
public String type = null;
public Geometry geometry = null;
public Properties properties = null;
}
class Geometry {
public String type = null;
HashSet<double[]> coordinates = null;
}
class Properties {
public String CONTOUR = null;
public int OBJECTID;
public String LAYER = null;
public double ELEVATION;
}
}
Why I can't do this iteratively after GSON has parsed the file?
The file is VERY large, and has 412,064 lines and is 27.5mb large. So doing that will take very long time.
NOTE: this parsing happens every time this app is run, so speed is necessary.
Thanks
You can register a TypeAdapter to modify values as they're read:
public class GsonDoubleAdapterTest {
public static void main(String[] args) {
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Double.class, new DoubleAdapter());
Gson gson = builder.create();
Foo foo = gson.fromJson("{\"baz\": 0.123456}", Foo.class);
System.out.println(foo);
}
}
/**
* A type adapter that rounds doubles during read.
*/
class DoubleAdapter extends TypeAdapter<Double> {
#Override
public void write(JsonWriter out, Double value) throws IOException {
out.value(value);
}
#Override
public Double read(JsonReader in) throws IOException {
return new BigDecimal(in.nextDouble()).setScale(4, RoundingMode.HALF_UP).doubleValue();
}
}
class Foo {
private Double baz;
public Double getBaz() {
return baz;
}
public void setBaz(Double baz) {
this.baz = baz;
}
#Override
public String toString() {
return "Foo[baz=" + baz + ']';
}
}

Deserialize a value which can be an array or atomic

I'm using Gson and want to deserialize the following JSON alternatives into the same class Values. In the latter case I would like to receive a List of just one element. Is there a way to accomplish this in Gson without having to write a custom deserializer?
//Array:
{
"Value": [205.4, 13.5]
}
//Single value:
{
"Value": 205.4
}
Deserialize both into:
public static class Values {
private List<Double> Value;
}
There is no way to do this in Gson unless using custom TypeAdapter.
public class AwesomeType extends ArrayList<Double> {
...
}
public class AwesomeTypeAdapter extends TypeAdapter<AwesomeType> {
#Override
public void write(JsonWriter out, AwesomeType value) throws IOException {
...
}
#Override
public AwesomeType read(JsonReader in) throws IOException {
AwesomeType result = new AwesomeType();
if (in.peek() == JsonToken.BEGIN_ARRAY) {
in.beginArray();
while (in.peek() != JsonToken.END_ARRAY)
result.add(in.nextDouble());
in.endArray();
} else {
result.add(in.nextDouble());
}
return result;
}
}
Register this type adapter to your Gson and use this class in your model instead of List<Double>.
As #BornToCode mentioned the solution is to write a custom TypeAdapter and register it with the GsonBuilder:
public class ListTypeAdapter extends TypeAdapter<List<Double>> {
#Override
public void write(final JsonWriter writer, final List<Double> doubles) throws IOException {
writer.beginArray();
for (final double value : doubles) {
writer.value(value);
}
writer.endArray();
}
#Override
public List<Double> read(final JsonReader reader) throws IOException {
final List<Double> doubles = new ArrayList<>();
if (reader.peek() == JsonToken.BEGIN_ARRAY) {
reader.beginArray();
while (reader.hasNext()) {
doubles.add(reader.nextDouble());
}
reader.endArray();
} else {
doubles.add(reader.nextDouble());
}
return doubles;
}
}
Register it:
GSONBUILDER.registerTypeAdapter(new TypeToken<List<Double>>(){}.getType(),
new ListTypeAdapter().nullSafe());

how to avoid jackson escaping backslash?

I set "this\'s my case!" to an object's field.
Calling writeAsString, output is "this\\\'s my case!".
But I expect "this\'s my case!".
How can I get what I want ?
public class CommonUtils {
public static ObjectMapper objectMapper = new ObjectMapper();
public static ObjectMapper getObjectMapperInstance(){
return objectMapper;
}
public static void main(String[] args) throws IOException {
CommonUtils commonUtils = new CommonUtils();
commonUtils.test();
}
public void test() throws IOException {
List<MyObject> list = new ArrayList<MyObject>();
String xx = "page://list?params={\"city\"}";
list.add(new MyObject(1,xx));
}
class MyObject{
public MyObject(int tag,String str){
this.tag = tag;
this.str = str;
}
int tag;
String str;
public int getTag() {
return tag;
}
public void setTag(int tag) {
this.tag = tag;
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
}
}
Output of above code:
[ {
"tag" : 1,
"str" : "page://list?params={\\"city\\"}]
What I want is:
[ {
"tag" : 1,
"str" : "page://list?params={\"city\"}]
If you Change the String xx to
String xx = "page://list?params={\\\"city\\\"}"; //page://list?params={\"city\"}
You will get desired result;
[ { "tag" : 1, "str" : "page://list?params={\"city\"}]

how to identify class by json attribute name using GSON

I have following json:
{
"list": [
{
"BaseClass": {
"id": 0
}
},
{
"ExtendedClass1": {
"id": 1,
"sum": 100
}
},
{
"ExtendedClass1_1": {
"id": 2,
"sum": 200,
"expr": "text"
}
},
{
"ExtendedClass2": {
"id": 3,
"total": 300
}
}
]
}
Also I have following classes with declared inheritance:
MetaClass.java
import java.util.ArrayList;
import com.google.gson.Gson;
public class MetaClass{
public ArrayList<BaseClass> list = new ArrayList<BaseClass>();
public static void main(String[] args) {
String json = "{\"list\":[{\"BaseClass\":{\"id\":0}},{\"ExtendedClass1\":{\"id\":1,\"sum\":100}},{\"ExtendedClass1_1\":{\"id\":2,\"sum\":200,\"expr\":\"text\"}},{\"ExtendedClass2\":{\"id\":3,\"total\":300}}]}";
MetaClass gson = new Gson().fromJson(json, MetaClass.class);
}
}
BaseClass.java
public class BaseClass{
public int id;
public BaseClass() {
}
}
ExtendedClass1.java
public class ExtendedClass1 extends BaseClass{
public ExtendedClass1() {
}
public int sum;
}
ExtendedClass2.java
public class ExtendedClass2 extends BaseClass {
public ExtendedClass2() {
}
public int total;
}
ExtendedClass1_1.java
public class ExtendedClass1_1 extends ExtendedClass1 {
public ExtendedClass1_1() {
}
public String expr;
}
Also, there could be a lot of such classes with multilevel inheritance. I try to make this example simpler. How correctly parse mentioned json string? Assume please that I could not change input json, only I can change classes and write custom fromJson command somehow...
EDIT: Of course, I can add to BaseClass.java all attributes that could be met in json (see below), but it seems not elegant solution.
public ExtendedClass1 ExtendedClass1;
public ExtendedClass2 ExtendedClass2;
public ExtendedClass1_1 ExtendedClass1_1;
You can write a custom TypeAdapter and register it to gsonBuilder. In your custom type adapter's read method, you have to manage mappings to create correct instances of the classes that you defined. I used the tags of your list json array's items:
public class CustomTypeAdapter extends TypeAdapter<BaseClass> {
#Override
public BaseClass read(JsonReader in) throws IOException {
BaseClass item = null;
Gson gson = new Gson();
JsonParser jsonParser = new JsonParser();
JsonObject jo = (JsonObject)jsonParser.parse(in);
JsonElement je = null;
if ((je = jo.get("BaseClass")) != null) {
item = gson.fromJson(je, BaseClass.class);
} else if((je = jo.get("ExtendedClass1")) != null) {
item = gson.fromJson(je, ExtendedClass1.class);
} else if((je = jo.get("ExtendedClass1_1")) != null) {
item = gson.fromJson(je, ExtendedClass1_1.class);
} else if((je = jo.get("ExtendedClass2")) != null) {
item = gson.fromJson(je, ExtendedClass2.class);
}
return item;
}
#Override
public void write(JsonWriter out, BaseClass item) throws IOException {
throw new IllegalArgumentException("TypeAdapter.write method not implemented!");
}
}
Test:
String json = "{\"list\":[{\"BaseClass\":{\"id\":0}},{\"ExtendedClass1\":{\"id\":1,\"sum\":100}},{\"ExtendedClass1_1\":{\"id\":2,\"sum\":200,\"expr\":\"text\"}},{\"ExtendedClass2\":{\"id\":3,\"total\":300}}]}";
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(BaseClass.class, new CustomTypeAdapter());
Gson gson = gsonBuilder.create();
java.lang.reflect.Type listType = new com.google.gson.reflect.TypeToken<List<BaseClass>>() {}.getType();
JsonArray jsonList = (JsonArray) (gson.fromJson(json, JsonObject.class).get("list"));
List<BaseClass> itemList = gson.fromJson(jsonList, listType);

Categories

Resources