Monty Swanson
Monty Swanson

Reputation: 795

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?

Upvotes: 0

Views: 537

Answers (3)

Monty Swanson
Monty Swanson

Reputation: 795

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.

Upvotes: 0

Turo
Turo

Reputation: 4924

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"

Upvotes: 1

Jan
Jan

Reputation: 13858

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"
  } ]
}

Upvotes: 1

Related Questions