Java GSON Error: JSON document was not fully consumed - java

So I have a JSON document that I want to read with different values including array like below
{ "name": "MacBook", "price": 1299, "stock": 10, "picture": "macbook.jpeg", "categories": [{"id": 1,"name": "macbook"},{"id": 2, "name":"notebook"}]}
I created a couple of POJO java classes to read them:
1 - Class (Product.java)
package models;
import java.util.ArrayList;
public class Product {
String name;
int price;
int stock;
String picture;
public ArrayList<Categories> categories;
public Product(String name, int price, int stock, String picture) {
this.name = name;
this.price = price;
this.stock = stock;
this.picture = picture;
this.categories = new ArrayList<>();
}
public void setName(String name) {
this.name = name;
}
public void setPrice(int price) {
this.price = price;
}
public void setStock(int stock) {
this.stock = stock;
}
public void setPicture(String picture) {
this.picture = picture;
}
public void setCategories(ArrayList<Categories> categories) {
this.categories = categories;
}
public String getName() {
return name;
}
public int getPrice() {
return price;
}
public int getStock() {
return stock;
}
public String getPicture() {
return picture;
}
public ArrayList<Categories> getCategories() {
return categories;
}
#Override
public String toString() {
return "Product{" +
"productName='" + name + '\'' +
", productPrice=" + price +
", productStock=" + stock +
", productPicture='" + picture + '\'' +
", categories=" + categories +
'}';
}
}
2 Class (Categories.java) to read the array
package models;
public class Categories {
private int id;
private String description;
public int getId() {
return id;
}
public String getDescription() {
return description;
}
public void setId(int id) {
this.id = id;
}
public void setDescription(String description) {
this.description = description;
}
public Categories(int id, String description) {
this.id = id;
this.description = description;
}
#Override
public String toString() {
return "Category{" + "id=" + id + ", description=" + description + '}';
}
}
And this is the main
package p3;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import models.Product;
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
Gson gson = new GsonBuilder()
.setLenient()
.create();
String fichero = "";
try (BufferedReader br = new BufferedReader(new FileReader("src/res/FitxersJSON/products.json"))) {
String linea;
while ((linea = br.readLine()) != null) {
fichero += linea;
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
Product productObject = gson.fromJson(fichero.toString(), Product.class);
System.out.println(productObject);
}
}
For some reason when I execute the main I get this error
Exception in thread "main" com.google.gson.JsonIOException: JSON document was not fully consumed.
at com.google.gson.Gson.assertFullConsumption(Gson.java:861)
at com.google.gson.Gson.fromJson(Gson.java:854)
at com.google.gson.Gson.fromJson(Gson.java:802)
at com.google.gson.Gson.fromJson(Gson.java:774)
at p3.Main.main(Main.java:42)
I have tried formating the JSON document but looks like everything is ok because I can clearly read it printing the "linea" value in each loop.
Thank you in advance.
[EDIT]
I solved the problem by adding "[" and "]" at the beginning and the end of the JSON file and also "," to all lines excepting the last one.
package p3;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import models.Categories;
import models.Product;
import java.io.*;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
public class Main {
public static void main(String[] args) {
ex2_readProducts();
ex3_addProducts();
}
private static void ex2_readProducts() {
Gson gson = new Gson();
Type collectionType = new TypeToken<Collection<Product>>() {
}.getType();
String file = "";
try (BufferedReader br = new BufferedReader(new FileReader("src/resources/products.json"))) {
String linea;
System.out.println("***************************** Reading the JSON file *********************************");
while ((linea = br.readLine()) != null) {
file += linea;
}
Collection<Product> enums = gson.fromJson(file, collectionType);
int counter = 0;
for (Product r : enums) {
counter++;
System.out.println("Product nº: " + counter );
System.out.println(r);
}
System.out.println("Result: " + counter + " products read from the file" );
System.out.println("***************************** Finished reading the JSON file *********************************");
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
public static void ex3_addProducts() {
Gson gson = new Gson();
Categories c1 = new Categories(1, "tablet");
Categories c2 = new Categories(2, "game");
Categories c3 = new Categories(3, "phone");
Categories c4 = new Categories(5, "smartwatch");
Categories c5 = new Categories(9, " scooter");
Product p1 = new Product("ipad32", 1200, 23, "ipad32.jpg");
Product p2 = new Product("soccer 3000", 100, 500, "soccer.jpg");
Product p3 = new Product("pixel", 900, 900, "pixel.jpg");
Product p4 = new Product("mi watch", 300, 23, "miwatch.jpg");
Product p5 = new Product("mi scooter 365", 365, 23, "miscooter.jpg");
ArrayList<Categories> categoriesArrayList1;
categoriesArrayList1 = new ArrayList<>(Arrays.asList(c1, c3));
ArrayList<Categories> categoriesArrayList2;
categoriesArrayList2 = new ArrayList<>(Arrays.asList(c1, c2, c3));
ArrayList<Categories> categoriesArrayList3;
categoriesArrayList3 = new ArrayList<>(Arrays.asList(c1, c4, c3));
ArrayList<Categories> categoriesArrayList4;
categoriesArrayList4 = new ArrayList<>(Arrays.asList(c1, c3));
ArrayList<Categories> categoriesArrayList5;
categoriesArrayList5 = new ArrayList<>(Arrays.asList(c5, c1));
p1.setCategories(categoriesArrayList1);
p2.setCategories(categoriesArrayList2);
p3.setCategories(categoriesArrayList3);
p4.setCategories(categoriesArrayList4);
p5.setCategories(categoriesArrayList5);
Product[] productsArray = {p1, p2, p3, p4, p5};
try (BufferedWriter br = new BufferedWriter(new FileWriter("src/resources/products2.json"))) {
System.out.println("********************** Adding products to a new file: *********************************");
br.write("[");
br.newLine();
int counter = 0;
for (int i = 0; i < productsArray.length; i++) {
System.out.println("Product nº: " + (i+1) + '\n' + productsArray[i]);
String json = gson.toJson(productsArray[i]);
br.write(json);
if (i != productsArray.length - 1) {
br.write(",");
}
br.newLine();
counter = (i+1);
}
br.write("]");
System.out.println("Result: " + counter + " products added to the file" );
System.out.println("**************************** Finished adding products *****************************");
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}

First of all you are using Department instead of Categories in the java class. As I see it contains different fields. I believe your problem is inside the json file or Main class reading the file. Using Guava gives you easier reading files. See my code:
products.json
{
"name": "MacBook",
"price": 1299,
"stock": 10,
"picture": "macbook.jpeg",
"categories": [
{
"id": 1,
"name": "macbook"
},
{
"id": 2,
"name": "notebook"
}
]
}
Main.class
package com.test;
import com.google.common.io.Resources;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.nio.charset.StandardCharsets;
public class Main {
public static void main(String[] args) throws Exception {
Gson gson = new GsonBuilder()
.create();
String products = Resources.toString(Resources.getResource("products.json"), StandardCharsets.UTF_8).trim();
Product productObject = gson.fromJson(products, Product.class);
System.out.println(productObject);
}
}
output is
Product{name='MacBook', price=1299, stock=10, picture='macbook.jpeg', categories=[Category{id=1, name='macbook'}, Category{id=2, name='notebook'}]}

I think main problem that in json you have {"id": 1,"name": "macbook"} but in java class Categories you use private String description;, how json parser should understand that description and name are same field?
In my opioion, you should try to use name insted of description, for example
package models;
public class Categories {
private int id;
private String name;
public int getId() {
return id;
}
public String getName() {
return name;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
...
}

Related

How to get string array from json object in deserialize method

I have some json object
{
"name": "John",
"age": 29,
"bestFriends": [
"Stan",
"Nick",
"Alex"
]
}
Here is my implementation of JsonDeserializer:
public class CustomDeserializer implements JsonDeserializer<Person>{
#Override
public Person deserialize(JsonElement json, Type type, JsonDeserializationContext cnxt){
JsonObject object = json.getAsJsonObject();
String name = new String(object.get("name").getAsString());
Integer age = new Integer(object.get("age").getAsInt());
String bestFriends[] = ?????????????????????????????????
return new Person(name, age, bestFriends);
}
}
How to get string array from json object here using GSON library?
Thanks a lot!
For the deserializer you can just loop over the ArrayNode and add the values to your String[] one after another.
ArrayNode friendsNode = (ArrayNode)object.get("bestFriends");
List<String> bestFriends = new ArrayList<String>();
for(JsonNode friend : friendsNode){
bestFriends.add(friend.asText());
}
//if you require the String[]
bestFriends.toArray();
Try this this will work for you. Thanks.
package test;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
class ID{
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#Override
public String toString() {
return "ID [id=" + id + "]";
}
}
public class Test {
public static void main(String[] args) {
ObjectMapper mapper = new ObjectMapper();
String jsonText = "{\"id\" : \"A001\"}";
//convert to object
try {
ID id = mapper.readValue(jsonText, ID.class);
System.out.println(id);
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I want to thank all who responded on my question and in the same time i find my decision (which is below) as the most fitting answer. Because i don't need to use any other libraries except GSON.
When i asked my question i didn't know that com.google.gson.TypeAdapter is more efficient instrument than JsonSerializer/JsonDeserializer.
And here below i have found decision for my problem:
package mytypeadapter;
import com.google.gson.Gson;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
public class Main {
static class Person{
String name;
int age;
String[] bestFriends;
Person() {}
Person(String name, int population, String... cities){
this.name = name;
this.age = population;
this.bestFriends = cities;
}
}
public static void main(String[] args) {
class PersonAdapter extends TypeAdapter<Person>{
#Override
public Person read (JsonReader jsonReader) throws IOException{
Person country = new Person();
List <String> cities = new ArrayList<>();
jsonReader.beginObject();
while(jsonReader.hasNext()){
switch(jsonReader.nextName()){
case "name":
country.name = jsonReader.nextString();
break;
case "age":
country.age = jsonReader.nextInt();
break;
case "bestFriends":
jsonReader.beginArray();
while(jsonReader.hasNext()){
cities.add(jsonReader.nextString());
}
jsonReader.endArray();
country.bestFriends = cities.toArray(new String[0]);
break;
}
}
jsonReader.endObject();
return country;
}
#Override
public void write (JsonWriter jsonWriter, Person country) throws IOException{
jsonWriter.beginObject();
jsonWriter.name("name").value(country.name);
jsonWriter.name("age").value(country.age);
jsonWriter.name("bestFriends");
jsonWriter.beginArray();
for(int i=0;i<country.bestFriends.length;i++){
jsonWriter.value(country.bestFriends[i]);
}
jsonWriter.endArray();
jsonWriter.endObject();
}
}
Gson gson = new GsonBuilder()
.registerTypeAdapter(Person.class, new PersonAdapter())
.setPrettyPrinting()
.create();
Person person, personFromJson;
person = new Person ("Vasya", 29, "Stan", "Nick", "Alex");
String json = gson.toJson(person);
personFromJson = new Person();
personFromJson = gson.fromJson(json, personFromJson.getClass());
System.out.println("Name = "+ personFromJson.name);
System.out.println("Age = "+ personFromJson.age);
for(String friend : personFromJson.bestFriends){
System.out.println("Best friend "+ friend);
}
}
}

DAO "IF" error when adding a company to contact

I'm creating a restaurant booking system and I have created the customer class but as part of the class you have be able to extend it so a company can add a contact.
I have a customer class, a company class and a TextCustomerDAO. inside the DAO is where i'm getting the error. When I try to say "If 'Y" then add a company contact" if no then just add customer. I can just add customer but when I try to add in the company contact i get an error
TextCustomerDAO: error just after the if statement where it says
contact = companyContact.getContact();
package projects.dao.textdao;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Path;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import projects.Customer;
import restaurant.dao.CustomerDAO;
import projects.Company;
public class TextCustomerDAO extends CustomerDAO {
static final char DELIMITER=':';
#Override
public List<Customer> loadCustomers(Path path) {
List<Customer> customers = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new FileReader(path.toString()))) {
Customer c = null;
Company co = null;
int customerId;
String customerName, customerPhone, customerAddress, customerEmail, contact;
String[] temp;
String line = br.readLine();
while(line!=null){
temp=line.split(Character.toString(DELIMITER));
customerId = Integer.parseInt(temp[0]);
customerName = temp[1];
customerPhone = temp[2];
customerAddress = temp[3];
customerEmail = temp[4];
if (temp.length==6){
String companyContact = temp[5];
contact = companyContact.getContact();
co = new Company(customerId, customerName, customerPhone, customerAddress, customerEmail, contact);
customers.add(co);
}
else {
c = new Customer(customerId,customerName, customerPhone, customerAddress, customerEmail);
customers.add(c);
}
line = br.readLine();
}
br.close();
} catch (IOException ex) {
Logger.getLogger(TextCustomerDAO.class.getName()).log(Level.SEVERE, null, ex);
}
return customers;
}
#Override
public void storeCustomers(Path path, List<Customer> customers) {
try (PrintWriter output = new PrintWriter(path.toFile())) {
for (Customer c:customers) {
output.println(toFileString(c));
}
output.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(TextCustomerDAO.class.getName()).log(Level.SEVERE, null, ex);
}
}
public String toFileString(Customer c) {
return Integer.toString(c.getCustomerId()) + DELIMITER +
c.getCustomerName() + DELIMITER +
c.getCustomerPhone() + DELIMITER +
c.getCustomerAddress() + DELIMITER +
c.getCustomerEmail() + DELIMITER;
}
public String toFileString(Company co) {
return Integer.toString(co.getCustomerId()) + DELIMITER +
co.getCustomerName() + DELIMITER +
co.getCustomerPhone() + DELIMITER +
co.getCustomerAddress() + DELIMITER +
co.getCustomerEmail() + DELIMITER +
co.getContact() + DELIMITER;
}
}
Customer Class:
public class Customer{
private int customerId;
private String customerName;
private String customerPhone;
private String customerAddress;
private String customerEmail;
private static int numberOfCustomers=0;
public Customer()
{
this.customerId = 0;
this.customerName = null;
this.customerPhone = null;
this.customerAddress = null;
this.customerEmail = null;
numberOfCustomers++;
}
public Customer(int customerId, String customerName, String customerPhone,
String customerAddress, String customerEmail)
{
this.customerId = customerId;
this.customerName = customerName;
this.customerPhone = customerPhone;
this.customerAddress = customerAddress;
this.customerEmail = customerEmail;
numberOfCustomers++;
}
public static int getNumberOfCustomers() {
return numberOfCustomers;
}
public int getCustomerId()
{
return customerId;
}
public void setCustomerId(int customerId)
{
this.customerId = customerId;
}
public String getCustomerName()
{
return customerName;
}
public void setCustomerName(String customerName)
{
this.customerName = customerName;
}
public String getCustomerPhone()
{
return customerPhone;
}
public void setCustomerPhone(String customerPhone)
{
this.customerPhone = customerPhone;
}
public String getCustomerAddress()
{
return customerAddress;
}
public void setCustomerAddress(String customerAddress)
{
this.customerAddress = customerAddress;
}
public String getCustomerEmail()
{
return customerEmail;
}
public void setCustomerEmail(String customerEmail)
{
this.customerEmail = customerEmail;
}
#Override
public String toString() {
return "customer id: " + getCustomerId() + ", " +
"customer name: " + getCustomerName() + ", " +
"customer phone: " + getCustomerPhone() + ", " +
"customer address: " + getCustomerAddress() + ", " +
"customer email: " + getCustomerEmail();
}
}
Company Class:
package projects;
public class Company extends Customer {
private String contact;
public Company() {
super();
this.contact = null;
}
public Company(int customerId, String customerName, String customerPhone, String customerAddress, String customerEmail, String contact) {
super(customerId, customerName, customerPhone, customerAddress, customerEmail);
this.contact = contact;
}
public String getContact() {
return this.contact;
}
public void setContact(String contact) {
this.contact = contact;
}
#Override
public String toString() {
return super.toString() + "Company Contact" + getContact();
}
}
Sorry if this is an obvious error but i have been trying for some time to fix the problem. If someone could assist or point me in the right direction it would be greatly appreciated.
Thanks

Rest client using Jersey returns empty object

im trying to develop a simple RESTful webservice client. Using java and the javax jersey+dependencies. My problem is when trying to convert from the XML the object comes in, it returns an empty object.
The test is a simple test. I whish to get the language with a specific id, from my test i can see that the XML im getting is the same as in a browser.
The code for the classes is as follows:
Language
package data;
import javax.xml.bind.annotation.*;
#XmlRootElement(name = "prestashop")
#XmlType
public class Language {
private int id;
private String name;
private String iso_code;
private String language_code;
private boolean active;
private boolean is_rtl;
private String date_format_lite;
private String date_format_full;
public Language() {
}
public Language(String name, String iso_code, String date_format_lite,
String date_format_full) {
this.name = name;
this.iso_code = iso_code;
this.date_format_lite = date_format_lite;
this.date_format_full = date_format_full;
}
public Language(int id, String name, String iso_code, String language_code,
boolean active, boolean is_rtl, String date_format_lite,
String date_format_full) {
this.id = id;
this.name = name;
this.iso_code = iso_code;
this.language_code = language_code;
this.active = active;
this.is_rtl = is_rtl;
this.date_format_lite = date_format_lite;
this.date_format_full = date_format_full;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIso_code() {
return iso_code;
}
public void setIso_code(String iso_code) {
this.iso_code = iso_code;
}
public String getLanguage_code() {
return language_code;
}
public void setLanguage_code(String language_code) {
this.language_code = language_code;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public boolean isIs_rtl() {
return is_rtl;
}
public void setIs_rtl(boolean is_rtl) {
this.is_rtl = is_rtl;
}
public String getDate_format_lite() {
return date_format_lite;
}
public void setDate_format_lite(String date_format_lite) {
this.date_format_lite = date_format_lite;
}
public String getDate_format_full() {
return this.date_format_full;
}
public void setDate_format_full(String date_format_full) {
this.date_format_full = date_format_full;
}
#Override
public String toString(){
return "Language ["
+ "id=" + id + ", "
+ "name=" + name + ", "
+ "iso_code=" + iso_code + ", "
+ "language_code=" + language_code + ", "
+ "active=" + active + ", "
+ "is_rtl=" + is_rtl + ", "
+ "date_format_lite=" + date_format_lite + ", "
+ "date_format_full=" + date_format_full+ ","
+ " ]";
}
}
Main
package webservicetest2;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
import data.Language;
import java.net.URI;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;
import javax.xml.bind.JAXBException;
public class WebServiceTest2 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws JAXBException {
try {
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
client.addFilter(new HTTPBasicAuthFilter("KEY", ""));
WebResource service = client.resource(getBaseURI());
System.out.println(service.path("languages")
.path("7")
.accept(MediaType.TEXT_XML)
.get(String.class));
Language language;
language = (Language) service.path("languages")
.path("7")
.accept(MediaType.TEXT_XML)
.get(Language.class);
System.out.println(language.toString());
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
private static URI getBaseURI() {
return UriBuilder.fromUri("http://localhost:8080/api").build();
}
}
The output
run:
<?xml version="1.0" encoding="UTF-8"?>
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<language>
<id><![CDATA[7]]></id>
<name><![CDATA[Danish]]></name>
<iso_code><![CDATA[da]]></iso_code>
<language_code><![CDATA[da]]></language_code>
<active><![CDATA[1]]></active>
<is_rtl><![CDATA[0]]></is_rtl>
<date_format_lite><![CDATA[Y-m-d]]></date_format_lite>
<date_format_full><![CDATA[Y-m-d H:i:s]]></date_format_full>
</language>
</prestashop>
Language [id=0, name=null, iso_code=null, language_code=null, active=false, is_rtl=false, date_format_lite=null, date_format_full=null, ]
BUILD SUCCESSFUL (total time: 0 seconds)
As you can see the XML im getting back has an object but the print of the object is an empty object. So something is wrong.
Sorry if simular question have been asked but havent been able to find any.

Simple-XML - how to serialize derived classes in a collection?

I want to serialize a object hierarchy including a list of objects which derive from the base class 'Thing'. This works fine, including deserialization - but XML-Simple insists in writing an attribute which specifies the actual used Java-class
when I create a xml file with the java code below, the content is like this:
<example1>
<things>
<fruit class="com.mumpitz.simplexmltest.Apple" id="17">
<sugar>212</sugar>
</fruit>
<fruit class="com.mumpitz.simplexmltest.Orange" id="25" weight="11.2"/>
</things>
</example1>
but this is not what I want.
I'd like to have
<example1>
<things>
<apple id="17">
<sugar>212</sugar>
</apple>
<orange id="25" weight="11.2"/>
</things>
</example1>
'apple' and 'orange' elements without a class attribute, not 'fruit' with such an attribute. Is this possible?
(The second xml complies to a existing schema; adding extra attributes is not an option)
Here's the code:
package com.mumpitz.simplexmltest;
import java.io.File;
import java.util.ArrayList;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
class Fruit {
#Attribute(name = "id")
protected final int id;
Fruit(
#Attribute(name = "id")
int id) {
this.id = id;
}
int getObjectId() {
return id;
}
}
#Root
class Apple extends Fruit {
private final int sugar;
#Element(type = Fruit.class)
public Apple(
#Attribute(name = "id")
int id,
#Element(name = "sugar")
int sugar) {
super(id);
this.sugar = sugar;
}
#Element(name = "sugar")
public int getSugar() {
return this.sugar;
}
#Override
public String toString() {
return "id: " + id + ", sugar: " + sugar;
}
}
#Root
class Orange extends Fruit {
#Attribute
public double weight;
public Orange(
#Attribute(name = "id")
int id) {
super(id);
}
#Override
public String toString() {
return "id: " + id + ", weight: " + weight;
}
}
#Root
public class Example1 {
#ElementList
public ArrayList<Fruit> things = new ArrayList<Fruit>();
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("things:\n");
for (int i=0; i<things.size(); i++) {
sb.append(" " + things.get(i).toString() + "\n");
}
return sb.toString();
}
//////////////////////////////////
static Example1 createDummy() {
Example1 d = new Example1();
d.things.add(new Apple(17, 212));
Orange or = new Orange(25);
or.weight = 11.2;
d.things.add(or);
return d;
}
static String msg;
static Example1 res;
static public String getMessage() {
String m = msg;
msg = null;
return m;
}
static public boolean write(String path) {
Serializer serializer = new Persister();
Example1 example = Example1.createDummy();
File result = new File(path);
try {
serializer.write(example, result);
} catch (Exception e) {
e.printStackTrace();
msg = e.getMessage();
return false;
}
return true;
}
static public boolean read(String path) {
Serializer serializer = new Persister();
File source = new File(path);
try {
res = serializer.read(Example1.class, source);
} catch (Exception e) {
e.printStackTrace();
msg = e.getMessage();
return false;
}
return true;
}
public static Object getResult() {
return res;
}
}
some hours later I found the solution. You simply have to
Read the manual
Use the #ElementListUnion annotation
package com.mumpitz.simplexmltest;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.ElementListUnion;
import org.simpleframework.xml.Root;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
// the base class
#Element
class Thing {
static int count=0;
Thing() {
this.id = ++count;
}
#Attribute
protected int id;
public int getId() {
return id;
}
}
// first derived class
#Element
class Car extends Thing {
#Attribute
private String name;
Car(#Attribute(name="name") String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override
public String toString() {
return "ID: " + id + " Car: " + name;
}
}
// second derived class
#Element
class House extends Thing {
#Attribute
private int price;
House(#Attribute(name="price") int price) {
this.price = price;
}
public int getPrice() {
return this.price;
}
#Override
public String toString() {
return "ID: " + id + " House: " + price;
}
}
// a class with a list of base class instances
#Root(name="ListOfThings")
public class Example4 {
// specify the derived classes used in the list
#ElementListUnion({
#ElementList(entry="house", inline=true, type=House.class),
#ElementList(entry="car", inline=true, type=Car.class)
})
private ArrayList<Thing> list = new ArrayList<Thing>();
public void add(Thing t) {
list.add(t);
}
public List<Thing> getProperties() {
return list;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Example4 contains " + list.size() + " elements:\n");
for (Thing t : list) {
sb.append(" " + t.toString() + "\n");
}
return sb.toString();
}
//////////////////////////////////
// test code
//////////////////////////////////
static String msg;
static Example4 res;
static public String getMessage() {
String m = msg;
msg = null;
return m;
}
static private Example4 createDummy() {
Example4 d = new Example4();
d.add(new Car("Mercedes"));
d.add(new House(34000000));
d.add(new Car("VW"));
d.add(new House(230000));
return d;
}
//////////////////////////////////
// serialize / deserialize
//////////////////////////////////
static public boolean write(String path) {
Serializer serializer = new Persister();
File result = new File(path);
Example4 example = Example4.createDummy();
try {
serializer.write(example, result);
} catch (Exception e) {
e.printStackTrace();
msg = e.getMessage();
return false;
}
return true;
}
static public boolean read(String path) {
Serializer serializer = new Persister();
File source = new File(path);
try {
res = serializer.read(Example4.class, source);
} catch (Exception e) {
e.printStackTrace();
msg = e.getMessage();
return false;
}
return true;
}
public static Object getResult() {
return res;
}
}

GSON throwing "Expected BEGIN_OBJECT but was BEGIN_ARRAY"?

I'm trying to parse a JSON string like this one
[
{
"updated_at":"2012-03-02 21:06:01",
"fetched_at":"2012-03-02 21:28:37.728840",
"description":null,
"language":null,
"title":"JOHN",
"url":"http://rus.JOHN.JOHN/rss.php",
"icon_url":null,
"logo_url":null,
"id":"4f4791da203d0c2d76000035",
"modified":"2012-03-02 23:28:58.840076"
},
{
"updated_at":"2012-03-02 14:07:44",
"fetched_at":"2012-03-02 21:28:37.033108",
"description":null,
"language":null,
"title":"PETER",
"url":"http://PETER.PETER.lv/rss.php",
"icon_url":null,
"logo_url":null,
"id":"4f476f61203d0c2d89000253",
"modified":"2012-03-02 23:28:57.928001"
}
]
into a list of objects.
List<ChannelSearchEnum> lcs = (List<ChannelSearchEnum>) new Gson().fromJson( jstring , ChannelSearchEnum.class);
Here's an object class I'm using.
import com.google.gson.annotations.SerializedName;
public class ChannelSearchEnum {
#SerializedName("updated_at")
private String updated_at;
#SerializedName("fetched_at")
private String fetched_at;
#SerializedName("description")
private String description;
#SerializedName("language")
private String language;
#SerializedName("title")
private String title;
#SerializedName("url")
private String url;
#SerializedName("icon_url")
private String icon_url;
#SerializedName("logo_url")
private String logo_url;
#SerializedName("id")
private String id;
#SerializedName("modified")
private String modified;
public final String get_Updated_at() {
return this.updated_at;
}
public final String get_Fetched_at() {
return this.fetched_at;
}
public final String get_Description() {
return this.description;
}
public final String get_Language() {
return this.language;
}
public final String get_Title() {
return this.title;
}
public final String get_Url() {
return this.url;
}
public final String get_Icon_url() {
return this.icon_url;
}
public final String get_Logo_url() {
return this.logo_url;
}
public final String get_Id() {
return this.id;
}
public final String get_Modified() {
return this.modified;
}
}
But it throws me with
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2
Any ideas how should I fix it?
The problem is you're telling Gson you have an object of your type. You don't. You have an array of objects of your type. You can't just try and cast the result like that and expect it to magically work ;)
The User guide for Gson Explains how to deal with this:
https://github.com/google/gson/blob/master/UserGuide.md
This will work:
ChannelSearchEnum[] enums = gson.fromJson(yourJson, ChannelSearchEnum[].class);
But this is better:
Type collectionType = new TypeToken<Collection<ChannelSearchEnum>>(){}.getType();
Collection<ChannelSearchEnum> enums = gson.fromJson(yourJson, collectionType);
The problem is that you are asking for an object of type ChannelSearchEnum but what you actually have is an object of type List<ChannelSearchEnum>.
You can achieve this with:
Type collectionType = new TypeToken<List<ChannelSearchEnum>>(){}.getType();
List<ChannelSearchEnum> lcs = (List<ChannelSearchEnum>) new Gson()
.fromJson( jstring , collectionType);
In my case JSON string:
[{"category":"College Affordability",
"uid":"150151",
"body":"Ended more than $60 billion in wasteful subsidies for big banks and used the savings to put the cost of college within reach for more families.",
"url":"http:\/\/www.whitehouse.gov\/economy\/middle-class\/helping middle-class-families-pay-for-college",
"url_title":"ending subsidies for student loan lenders",
"type":"Progress",
"path":"node\/150385"}]
and I print "category" and "url_title" in recycleview
Datum.class
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Datum {
#SerializedName("category")
#Expose
private String category;
#SerializedName("uid")
#Expose
private String uid;
#SerializedName("url_title")
#Expose
private String urlTitle;
/**
* #return The category
*/
public String getCategory() {
return category;
}
/**
* #param category The category
*/
public void setCategory(String category) {
this.category = category;
}
/**
* #return The uid
*/
public String getUid() {
return uid;
}
/**
* #param uid The uid
*/
public void setUid(String uid) {
this.uid = uid;
}
/**
* #return The urlTitle
*/
public String getUrlTitle() {
return urlTitle;
}
/**
* #param urlTitle The url_title
*/
public void setUrlTitle(String urlTitle) {
this.urlTitle = urlTitle;
}
}
RequestInterface
import java.util.List;
import retrofit2.Call;
import retrofit2.http.GET;
/**
* Created by Shweta.Chauhan on 13/07/16.
*/
public interface RequestInterface {
#GET("facts/json/progress/all")
Call<List<Datum>> getJSON();
}
DataAdapter
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Shweta.Chauhan on 13/07/16.
*/
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.MyViewHolder>{
private Context context;
private List<Datum> dataList;
public DataAdapter(Context context, List<Datum> dataList) {
this.context = context;
this.dataList = dataList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.data,parent,false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.categoryTV.setText(dataList.get(position).getCategory());
holder.urltitleTV.setText(dataList.get(position).getUrlTitle());
}
#Override
public int getItemCount() {
return dataList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder{
public TextView categoryTV, urltitleTV;
public MyViewHolder(View itemView) {
super(itemView);
categoryTV = (TextView) itemView.findViewById(R.id.txt_category);
urltitleTV = (TextView) itemView.findViewById(R.id.txt_urltitle);
}
}
}
and finally MainActivity.java
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private DataAdapter dataAdapter;
private List<Datum> dataArrayList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
}
private void initViews(){
recyclerView=(RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
loadJSON();
}
private void loadJSON(){
dataArrayList = new ArrayList<>();
Retrofit retrofit=new Retrofit.Builder().baseUrl("https://www.whitehouse.gov/").addConverterFactory(GsonConverterFactory.create()).build();
RequestInterface requestInterface=retrofit.create(RequestInterface.class);
Call<List<Datum>> call= requestInterface.getJSON();
call.enqueue(new Callback<List<Datum>>() {
#Override
public void onResponse(Call<List<Datum>> call, Response<List<Datum>> response) {
dataArrayList = response.body();
dataAdapter=new DataAdapter(getApplicationContext(),dataArrayList);
recyclerView.setAdapter(dataAdapter);
}
#Override
public void onFailure(Call<List<Datum>> call, Throwable t) {
Log.e("Error",t.getMessage());
}
});
}
}
Alternative could be
to make your response look like
myCustom_JSONResponse
{"master":[
{
"updated_at":"2012-03-02 21:06:01",
"fetched_at":"2012-03-02 21:28:37.728840",
"description":null,
"language":null,
"title":"JOHN",
"url":"http://rus.JOHN.JOHN/rss.php",
"icon_url":null,
"logo_url":null,
"id":"4f4791da203d0c2d76000035",
"modified":"2012-03-02 23:28:58.840076"
},
{
"updated_at":"2012-03-02 14:07:44",
"fetched_at":"2012-03-02 21:28:37.033108",
"description":null,
"language":null,
"title":"PETER",
"url":"http://PETER.PETER.lv/rss.php",
"icon_url":null,
"logo_url":null,
"id":"4f476f61203d0c2d89000253",
"modified":"2012-03-02 23:28:57.928001"
}
]
}
instead of
server_JSONResponse
[
{
"updated_at":"2012-03-02 21:06:01",
"fetched_at":"2012-03-02 21:28:37.728840",
"description":null,
"language":null,
"title":"JOHN",
"url":"http://rus.JOHN.JOHN/rss.php",
"icon_url":null,
"logo_url":null,
"id":"4f4791da203d0c2d76000035",
"modified":"2012-03-02 23:28:58.840076"
},
{
"updated_at":"2012-03-02 14:07:44",
"fetched_at":"2012-03-02 21:28:37.033108",
"description":null,
"language":null,
"title":"PETER",
"url":"http://PETER.PETER.lv/rss.php",
"icon_url":null,
"logo_url":null,
"id":"4f476f61203d0c2d89000253",
"modified":"2012-03-02 23:28:57.928001"
}
]
CODE
String server_JSONResponse =.... // the string in which you are getting your JSON Response after hitting URL
String myCustom_JSONResponse="";// in which we will keep our response after adding object element to it
MyClass apiResponse = new MyClass();
myCustom_JSONResponse="{\"master\":"+server_JSONResponse+"}";
apiResponse = gson.fromJson(myCustom_JSONResponse, MyClass .class);
After this it will be just any other GSON Parsing
This looks like a Json array list.Therefore its best to use ArrayList to handle the data. In your api end point add array list like this
#GET("places/")
Call<ArrayList<Place>> getNearbyPlaces(#Query("latitude") String latitude, #Query("longitude") String longitude);
according to GSON User guide, you cannot.
Collections Limitations
Can serialize collection of arbitrary objects but can not deserialize from it. Because there is no way for the user to indicate the type of the resulting object
Kotlin:
var list=ArrayList<Your class name>()
val listresult: Array<YOUR CLASS NAME> = Gson().fromJson(
YOUR JSON RESPONSE IN STRING,
Array<Your class name>:: class.java)
list.addAll(listresult)
You need to let Gson know additional type of your response as below
import com.google.common.reflect.TypeToken;
import java.lang.reflect.Type;
Type collectionType = new TypeToken<List<UserSite>>(){}.getType();
List<UserSite> userSites = gson.fromJson( response.getBody() , collectionType);
I am not sure if this is the best way to use GSON, but works for me. You can use some like this on the MainActivity:
public void readJson() {
dataArrayList = new ArrayList<>();
String json = "[\n" + IOHelper.getData(this) + "\n]\n";
Log.d(TAG, json);
try{
JSONArray channelSearchEnums = new JSONArray(json);
for(int i=0; i< channelSearchEnums.length(); i++)
{
JSONObject enum = channelSearchEnums.getJSONObject(i);
ChannelSearchEnum channel = new ChannelSearchEnum(
enum.getString("updated_at"), enum.getString("fetched_at"),
enum.getString("description"), enum.getString("language"),
enum.getString("title"), enum.getString("url"),
enum.getString("icon_url"), enum.getString("logo_url"),
enum.getString("id"), enum.getString("modified"))
dataArrayList.add(channel);
}
//The code and place you want to show your data
}catch (Exception e)
{
Log.d(TAG, e.getLocalizedMessage());
}
}
You only have strings, but if you would have doubles or int, you could put getDouble or getInt too.
The method of IOHelper class is the next (Here, the path is save on the internal Storage):
public static String getData(Context context) {
try {
File f = new File(context.getFilesDir().getPath() + "/" + fileName);
//check whether file exists
FileInputStream is = new FileInputStream(f);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
return new String(buffer);
} catch (IOException e) {
Log.e("TAG", "Error in Reading: " + e.getLocalizedMessage());
return null;
}
}
If you want more information about this, you can see this video, where I get the code of readJson(); and this thread where I get the code of getData().
public ChannelSearchEnum[] getChannelSearchEnum(Response response) {
return response.as(ChannelSearchEnum[].class, ObjectMapperType.GSON);
}
Above will solve and passing response will returned mapped object array of the class
Solution
I am using volley library. I parse response automatic in volley using GSON
[
{
"name": "Naruto: Shippuuden",
"description": "It has been two and a half years since Naruto Uzumaki left Konohagakure, the Hidden Leaf Village, for intense training following events which fueled his desire to be stronger. Now Akatsuki, the mysterious organization of elite rogue ninja, is closing in on their grand plan which may threaten the safety of the entire shinobi world.",
"Rating": "8.16",
"episode": 500,
"categorie":"Animation | Drama | Adventure",
"studio":"Studio Pierrot",
"img": "https://myanimelist.cdn-dena.com/images/anime/5/17407.jpg"
},
{
"name": "One Piece",
"description": "Gol D. Roger was known as the 'Pirate King',the strongest and most infamous being to have sailed the Grand Line. The capture and death of Roger by the World Government brought a change throughout the world. His last words before his death revealed the existence of the greatest treasure in the world, One Piece. It was this revelation that brought about the Grand Age of Pirates, men who dreamed of finding One Piece—which promises an unlimited amount of riches and fame—and quite possibly the pinnacle of glory and the title of the Pirate King.",
"Rating": "8.54",
"episode": 700,
"categorie":"Animation | Drama | Adventure",
"studio":"Toei Animation",
"img": "https://myanimelist.cdn-dena.com/images/anime/6/73245.jpg"
}
]
2.This my model
public class DataResponse implements Serializable {
#SerializedName("studio")
private String studio;
#SerializedName("img")
private String img;
#SerializedName("categorie")
private String categorie;
#SerializedName("Rating")
private String rating;
#SerializedName("name")
private String name;
#SerializedName("description")
private String description;
#SerializedName("episode")
private int episode;
public void setStudio(String studio){
this.studio = studio;
}
public String getStudio(){
return studio;
}
public void setImg(String img){
this.img = img;
}
public String getImg(){
return img;
}
public void setCategorie(String categorie){
this.categorie = categorie;
}
public String getCategorie(){
return categorie;
}
public void setRating(String rating){
this.rating = rating;
}
public String getRating(){
return rating;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setDescription(String description){
this.description = description;
}
public String getDescription(){
return description;
}
public void setEpisode(int episode){
this.episode = episode;
}
public int getEpisode(){
return episode;
}
#Override
public String toString(){
return
"Response{" +
"studio = '" + studio + '\'' +
",img = '" + img + '\'' +
",categorie = '" + categorie + '\'' +
",rating = '" + rating + '\'' +
",name = '" + name + '\'' +
",description = '" + description + '\'' +
",episode = '" + episode + '\'' +
"}";
}
}
my api method
define globle
private List<DataResponse> dataResponses = new ArrayList<>();
private void volleyAutomation(String url) {
JSONArray array = new JSONArray();
JsonArrayRequest request_json = new JsonArrayRequest(Request.Method.GET, url, array,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
dataResponses = Arrays.asList(gson.fromJson(response.toString(), DataResponse[].class));
rvList(dataResponses);
Log.d("respknce___", String.valueOf(dataResponses.size()));
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
}
});
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
requestQueue.add(request_json);
}

Categories

Resources