Reputation: 795
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
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
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
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