Reputation: 94
I need to work with Jsons containing loads of special characters and spaces. I've read somewhere else here on stack that the Gson library (for Java) does a very good job so I'm using that. While using the fromJson(Json string, object class) method to turn a Json string into an object, I noticed that as soon as the data in the string contains any special character or white space, an exception is thrown (Unterminated object). Removing the special characters makes it work as intended.
To better exemplify the situation:
ArrayList<Person> people = new ArrayList<Person>();
Person p1 = new Person("Matteo", 999);
Person p2 = new Person("Adam", 999);
Person p3 = new Person("Steve", 999);
people.add(p1);
people.add(p2);
people.add(p3);
String json = new Gson().toJson(people);
System.out.println(json);
ArrayList people2 = new Gson().fromJson(json, ArrayList.class);
for (int i = 0; i < people2.size(); i++) {
Person pn = new Gson().fromJson(people2.get(i).toString(), Person.class);
System.out.println(people2.get(i).toString());
System.out.println(pn.name);
}
class Person {
String name;
int age;
Person(String cname, int cage) {
name = cname;
age = cage;
}
}
The code above works as intended, BUT if instead of Matteo I type Ma:tteo or Ma tteo or any other string that contains special characters then it breaks.
So is there a way to circumvent this issue? Alternatively is there a better solution than using this library?
Thanks in advance
Upvotes: 2
Views: 6756
Reputation: 22977
Gson
does its work fine.
There are two problems with how you are using the Gson library:
You are using fromJson(String, Class<T>)
in conjunction with generics. The documentation states that when using generics, you should use fromJson(String, Type)
:
For the cases when the object is of generic type, invoke
fromJson(String, Type)
.
You are first deserializing the JSON string into a Java structure – in your case an ArrayList
– and then you are looping over it, and for each object, you are deserializing it again, relying on the toString()
method of the object contained in the ArrayList
. As a matter of fact, your list does not contain Person
objects at all, instead, it contains LinkedTreeMap
objects from the com.google.gson.internal
package. You can get the object's class by calling people2.get(i).getClass()
.
You really don't need to walk over the elements of this ArrayList
and deserialize the elements yourself. If it was required to walk over each list contained in your structure, it would be a world of hurt when that structure was more complex than yours.
Simply get rid of your for-loop and replace your toJson(String, Class<T>)
call with a call to fromJson(String, Type)
. That's all.
// We're using the TypeToken class, to handle generic types
Type type = new TypeToken<List<Person>>() { }.getType();
List<Person> newPeople = new Gson().fromJson(json, type);
// Print all names
newPeople.stream()
.map(t -> t.name)
.forEach(System.out::println);
Notes
A part of the source of the problem is that you are using a raw type (ArrayList
). Don't use raw types, they are only allowed for backward compatibility.
I need to work with Jsons containing loads of special characters and spaces.
It's still not clear what you mean with special characters. The JSON standard clearly defines what is allowed and what is not. Your JSON string should follow the standards, and then you're good to go.
Upvotes: 4
Reputation: 1872
Try with this code.
ArrayList<Person> people = new ArrayList<Person>();
Person p1 = new Person("Ma:tteo", 999);
Person p2 = new Person("Adam", 999);
Person p3 = new Person("Steve", 999);
people.add(p1);
people.add(p2);
people.add(p3);
Gson gson = new Gson();
String json = gson.toJson(people);
System.out.println(json);
List<Person> personList = gson.fromJson(json, new TypeToken<List<Person>>(){}.getType());
for (int i = 0; i < personList.size(); i++) {
Person person = personList.get(i);
System.out.println(person.toString());
System.out.println(person.name);
}
Upvotes: 1