JSON GSON.fromJson Java Objects - java

I am trying to load my Json into my class
public User() {
this.fbId = 0;
this.email = "";
this.name = "";
this.thumb = "";
this.gender = "";
this.location = "";
this.relationship = null;
this.friends = new ArrayList();
}
{
users:{
user:{
name:'the name',
email:'some#email.com',
friends:{
user:{
name:'another name',
email:'this#email.com',
friends:{
user:{
name:'yet another name',
email:'another#email.com'
}
}
}
}
}
}
}
I am struggling to get GSON to load the user details into the above Java object with the following code
User user = gson.fromJson(this.json, User.class);

The JSON is invalid. A collection is not to be represented by {}. It stands for an object. A collection/array is to be represented by [] with commaseparated objects.
Here's how the JSON should look like:
{
users:[{
name: "name1",
email: "email1",
friends:[{
name: "name2",
email: "email2",
friends:[{
name: "name3",
email: "email3"
},
{
name: "name4",
email: "email4"
}]
}]
}]
}
(note that I added one more friend to the deepest nested friend, so that you understand how to specify multiple objects in a collection)
Given this JSON, your wrapper class should look like this:
public class Data {
private List<User> users;
// +getters/setters
}
public class User {
private String name;
private String email;
private List<User> friends;
// +getters/setters
}
and then to convert it, use
Data data = gson.fromJson(this.json, Data.class);
and to get the users, use
List<User> users = data.getUsers();

Related

Convert Java object list to correct name value pair format in Json using Gson

I have a Java Class named User with
#Column(name = "id")
private Long id;
#NotNull
#Column(name = "NAME")
private String name;
I am trying to get some details in a list and convert it into JSOn like so:
Session session = this.sessionFactory.getCurrentSession();
String queryString="select id,name from User where unit=:name";
Query query= sessionFactory.getCurrentSession().createQuery(queryString);
query.setParameter("name", name);
List<User> users= (List<User>) query.list();
Gson gson = new GsonBuilder().setPrettyPrinting().create();
Map<String, List<User>> wrap = new HashMap<>();
wrap.put("users", users); // wrap user list in a map
String json = gson.toJson(wrap);
This produces a JSON
{
"users": [
[
1,
"Room"
],
[
2,
"Regi"
],
]
}
How do I change it so that I get a JSON like
{
"users": [
[
"id":1,
"name":"Rovom"
],
[
"id":2,
"name":"Regi"
],
]
}
Edit
I realized it is the query that is causing the issue. If i use
String queryString="from User where unit=:name";
It gives the correct format. How do I fix this?
Whith jackson, it'll look like this:
String json = new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueToString(wrap);
You'd want jackson-core and jackson-databind for this at least.
Full example using Jackson:
public static class User {
private Long id;
private String name;
public User(long i, String n) {
id = i;
name = n;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public static void main(String... args) {
try {
Map<String,Object> map = new HashMap<>();
map.put("users", Arrays.asList(new User(1, "Stack"), new User(2, "Overflow")));
System.out.println(new ObjectMapper().writerWithDefaultPrettyPrinter()
.writeValueAsString(map));
} catch (Exception e) {
e.printStackTrace();
}
}
produced this output:
{
"users" : [ {
"id" : 1,
"name" : "Stack"
}, {
"id" : 2,
"name" : "Overflow"
} ]
}
Hm, looks like type erasure at runtime.
Your List<User> is with the first query actually a List<Object[]> as which it got serialized. Would you try to access an User-object out of the list, you'd get a runtime error, I suppose.
See hibernate documentation:
Return the query results as a List. If the query contains multiple
results pre row, the results are returned in an instance of Object[].
EDIT
to get a list of Users with only the two fields filled, create the apropriate constructur and use a query like
select new package.path.to.class.User(id,name) from User where unit=:name"
As mentioned by user #Turo this is because of type erasure at runtime.
To fix this, the query has to be changed to
String queryString="select id,name from User where unit=:name";
Query query= sessionFactory.getCurrentSession().createSQLQuery(queryString).addScalar("name", new StringType()).addScalar("id", new IntType()).setResultTransformer(Transformers.aliasToBean(User.class));
query.setParameter("name", name);
the addScalar() will map the values to the User objects and this gives the required result.

How to map A JSON single item from a list<int, String) to String with Jackson?

In some incoming JSON there is a list
"age" : 27,
"country", USA,
"fields": [
{
"id": 261762251,
"value": "Fred"
},
{
"id": 261516162,
"value": "Dave"
},
]
I know the key int for what I am looking for [261762251].
I would like to map that to a plain String field firstname in the User object with the rest of the bottom level fields from the JSON. I have tried extending com.fasterxml.jackson.databind.util.StdConverter and adding the annotation #JsonSerialize(converter=MyConverterClass.class) to the variable in the User class with no luck.
My architecture is like this:
public class User {
private String age;
private String country;
private String firstname; // this is the field in the list that needs converting
// getters and setters
}
public class ApiClient{
public User getUsers(){
Response response;
//some code to call a service
return response.readEntity(User.class)
}
}
What is the best approach to achieve this?
You can try something like below:
class Tester
{
public static void main(String[] args) throws Exception {
String s1 = "{\"fields\": [ { \"id\": 261762251, \"value\": \"Fred\" }, { \"id\": 261516162, \"value\": \"Dave\" }]}";
ObjectMapper om = new ObjectMapper();
Myclass mine = om.readValue(s1, Myclass.class);
System.out.println(mine);
}
}
public class User {
private String age;
private String country;
private String firstname; // this is the field in the list that needs converting
#JsonProperty("fields")
private void unpackNested(List<Map<String,Object>> fields) {
for(Map<String,Object> el: fields) {
if((Integer)el.get("id") == 261762251) {
firstname = el.toString();
}
}
}
// getters and setters
}

How to query a json object in java?

I have a test.json file with data:
{
"name":"tet",
"id":"1",
"age" : "34"
}
Now when I query select * from test; should show me the result as
name id age
-----------
tet 1 34
Is it possible to directly query a JSON Object as we do for XML?
The popular Jackson XML library supports JsonPointer since version 2.3. This is a query language similar to XPath
Input
[{
"name":"tet",
"id":"1",
"age" : "34"
},{
"name":"tet",
"id":"1",
"age" : "34"
},{
"name":"tet",
"id":"1",
"age" : "34"
},{
"name":"tet",
"id":"1",
"age" : "34"
}]
Example
ObjectMapper objectMapper = new ObjectMapper();
JsonNode root = objectMapper.readTree(new File("foo.json"));
System.out.println(root.at("/0/name").asText());
I would say you can either try looking for a library which allows you to search throught JSON data or to convert your json to JSONObjects and query your data in a Object Oriented way.
Perhaps this thread will help:
Query a JSONObject in java
there is no way to query directly from the Json, if you want you have to create a new class that will do your requirement, OR you can use the ObjectMapper (download and add to your class path) from jackson-all-1.9.0.jar, and create a new transfer Object TestTO.java expose the setters and getters you will get your data like below..
1.create TestTO.java
public class TestTO{
private String name;
private int id;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
2.read your data from the object.
final ObjectMapper mapper = new ObjectMapper();
Test test = mapper.readValue(yourJson.json, TestTO.class);
String name = test.getName();
int id = test.getId();
int age = test.getAge();
if your json contains the multiple test objects, use an test array like below, it will give you the array of tests, you can iterate over and get the data, like below.
final ObjectMapper mapper = new ObjectMapper();
TestTO[] test = mapper.readValue(yourJson.json, TestTO.class[]);
for(Test tst:test){
String name = test.getName();
int id = test.getId();
int age = test.getAge();
}

transpose DBObject to json

I have a list of mongo db objects List from mongo fetch
for example the DBObject contains column name and order:
student name,1
student id,2
student address,3
I would like to transpose this data for datatables ui to json like so:
[
        { title: "student name" },
{ title: "student id" },
{ title: "student address" }
]
I looked up GSON lib but it seems like i need to add annotations to my objects - no intentions of doing so.
Suppose you have your Pojo like this:
class YourPojo {
private String title;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
You can build Gson json:
final JsonArray datasets = new JsonArray();
for (String key: dbObject.keySet()) {
JsonObject dataset = new JsonObject();
dataset.addProperty("title", key);
datasets.add(dataset);
}
And then convert it to your pojo:
Type listType = new TypeToken<ArrayList<YourPojo>>(){}.getType();
List<YourPojo> yourPojoList = new Gson().fromJson(datasets, listType);

Java - Jackson JSON Library and ObjectMapper.readValue

I have the following json data (patients.json):
{
"A" : {
"name" : "Tom",
"age" : 12
},
"B" : {
"name" : "Jim",
"age" : 54
}
}
Using the Jackson JSON library, how can I get something like the following:
HashMap<String, ???> patients = objectMapper.readValue(new File("patients.json"), ???);
String Aname = patients.get("A").get("name");
int Aname = patients.get("A").get("age");
Deserialize your JSON into Jackson's JSON Object type, ObjectNode. You can then traverse it as you see fit.
For example
ObjectNode patients = objectMapper.readValue(new File("test.json"), ObjectNode.class);
// you can check if it is actually an ObjectNode with JsonNode#isObject()
ObjectNode nodeA = (ObjectNode)patients.get("A");
String name = nodeA.get("name").asText();
int age = (int) nodeA.get("age").asLong();
Note that the methods asXyz() return default values if the target node cannot be converted to that type. You can check with the corresponding isXyz() methods before invoking them.
You could create a class to map your patients to;
private static class Patient {
#JsonProperty("name")
private String name;
#JsonProperty("age")
private int age;
public Patient() { }
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
Then read your json into it via jackson
HashMap<String, Patient> patients = objectMapper.readValue(new File("patients.json"), new TypeReference<HashMap<String,Patient>>() {});
Patient patientA = patients.get("A");
String patientAName = patientA.getName();
int pateintAAge = patientA.getAge();

Categories