Java object not being converted to JSON

Hi,

I'm sure this is a simple issue but I can't figure it out.

I have an object which I'm trying to return to the browser in JSON format, but for some reason the response I seem to be getting is a reference to the object rather than the object itself;

{"client":"model.Client@3eb1cf31"}

Open in new window


The code I'm using the generate the response is;

@GET
	@Produces("application/json")
	public Response get() {
		Client client = this.clientRepo.get(1);
		
		JSONObject response = new JSONObject();
		response.put("client", client);
		
		return Response.status(200).entity(response.toString()).build();
	}

Open in new window


However, if I put the object inside hashmap and then add the hashmap to the JSON object, the object is converted to JSON just fine.

@GET
	@Produces("application/json")
	public Response get() {
		Client client = this.clientRepo.get(1);
		
		HashMap r = new HashMap();
		r.put("client", client);
		
		JSONObject response = new JSONObject();
		response.put("response", r);
		
		return Response.status(200).entity(response.toString()).build();
	}

Open in new window


Obviously I could just use the hashmap method, but it seems like an unnecessary step.

Can anyone pin point why the first example doesn't work?

Thanks
SheppardDigitalAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

CEHJCommented:
You do of course need to cast the object placed into the response. You're doing that?
0
srikoteshCommented:
u need type cast the object into client type

after casting ur object
do this
Response<Client> response = new Response<>();
if(client != null){
response.setSuccess(client );
}esle{
response.setWaring("no records");
}
0
SheppardDigitalAuthor Commented:
I'm casting the object when it's pulled from the database. Here's the method that returns the client object.

public Client get(Integer clientId) {
		Client client;
		
		try {
			Query query = this.entityManager.createQuery("SELECT c FROM Client c WHERE id = :id");
			client = (Client) query.setParameter("id", clientId).setMaxResults(1).getSingleResult();
		}
		catch (NoResultException e) {
			client = new Client();
		}
		finally {
			this.close();
		}
		
		return client;
	}

Open in new window


I've also tried casting the object as it's put into the response;

@GET
	@Produces("application/json")
	public Response get() {
		Client client = this.clientRepo.get(1);
		
		JSONObject response = new JSONObject();
		response.put("client", (Client) client);
		
		return Response.status(200).entity(response.toString()).build();
	}

Open in new window

0
Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

CEHJCommented:
I seem to be getting is a reference to the object rather than the object
That output is like that because Client does not override toString
0
SheppardDigitalAuthor Commented:
As you can tell, I'm pretty new to Java.

I don't really understand your comment, are you saying that the Client needs to have a toString() method which converts returns JSON?

Why does it work in the Client is in a HashMap or Collection? is it because they have their own toString() methods to handle the conversion?
0
CEHJCommented:
Please post the output found when it IS in a Map/Collection
0
SheppardDigitalAuthor Commented:
Output when I put the Client in a HashMap;

{"response":{"client":{"name":"Some company","id":1}}}

Open in new window


and here's the code to do it;

@GET
	@Produces("application/json")
	public Response get() {
		Client client = this.clientRepo.get(1);
		
		HashMap r = new HashMap();
		r.put("client", client);
		
		JSONObject response = new JSONObject();
		response.put("response", r);
		
		return Response.status(200).entity(response.toString()).build();
	}

Open in new window

0
CEHJCommented:
Not quite sure why that happens, as i don't know the APIs
0
CEHJCommented:
What IS that API btw?
0
srikoteshCommented:
Hi CEHJ,
that is hibernate, JPA implementation.

Hi Sheppard,
this part also looks good

Query query = this.entityManager.createQuery("SELECT c FROM Client c WHERE id = :id");
client = (Client) query.setParameter("id", clientId).setMaxResults(1).getSingleResult();

i think while setting this object of type client in @get method having issue.
while setting u r setting it map object.
instead of that

in response model class create one method which will set dirly object .
response.setSuccess(client);
0
SheppardDigitalAuthor Commented:
Hi srikotesh

Sorry, I don't fully understand what you're asking me to try?
0
srikoteshCommented:
@GET
	@Produces("application/json")
	public Response get() {
		Client client = this.clientRepo.get(1);
		
		JSONObject response = new JSONObject();
		response.put("client", client);//here instead of put do like
                response.setSuccess(urobject);
		
		return Response.status(200).entity(response.toString()).build();
	}

Open in new window

0
SheppardDigitalAuthor Commented:
The setSuccess method doesn't seem to exist on the response object.
0
srikoteshCommented:
u have to create response model class separately and create method which will take object as parameter.
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Firstly, I too am not sure why your Hashmap version is working the way it is. Something funky is going on there, that I can't get my head around.

Anyway, I guess the point of the matter is that JSONObject is not meant to do what you are trying to make it do. You are trying to get it to automatically "map" your Client POJO to a JSON string. All JSONObject is there to do is "hold" the JSON representation of an object but in an object rather than a string. You would need other libraries to do that for you such as (Jackson, Gson, and probably many others).

I am less familiar with JAX-RS API's that you are using, but my thought on the subject is that you shouldn't even need the JSONObject representation for this to work like you want it. I could be way off, but have you tried something like this code...

@GET
	@Produces("application/json")
	public Response get() {
		Client client = this.clientRepo.get(1);
		
		return Response.status(200).entity(client).build();
	}

Open in new window


You may need to explicitly add the required libraries to allow the automatic marshalling of object to JSON (which you would need with whatever way you end up going). If you need help determining what libraries these are, you will need to tell us what JAX-RS implementation you are using, and also it would help if you tell us what (if any) dependency manager you are using, eg. maven, ivy, gradle, etc.
0
SheppardDigitalAuthor Commented:
Hi mccarl,

Thanks for the feedback.

I don't really get that JSONObject is meant to hold your objects before conversion, if that was the case then surely using a HashMap would result it exactly the same output.

I was under the impression that the JSONObject is where you'd store the data to be converted to JSON, and later have it returned as JSON by the JSONObject. However, as mentioned previously, I'm pretty new to Java having worked with PHP for the last 15 years.

I'm using the Maven dependency manager, and below are the contents;

<dependencies>
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-bundle</artifactId>
<version>1.19</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20140107</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.19</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
<version>1.19</version>
</dependency>
<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.21</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.0-api</artifactId>
            <version>1.0.1.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.0.1.Final</version>
        </dependency>
        <dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.5.4</version>
</dependency>
</dependencies>

Open in new window

0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Did you try the code I posted above?

If it doesn't work straight up, perhaps "jersey" doesn't automatically use Jackson. There appears to be a jersey-json dependency that you could try adding to your maven pom.xml that might just make it work as it should.
0
SheppardDigitalAuthor Commented:
Hi,

Yes I tried the code above, and sadly it was still doing exactly the same.

Instead of using a JSONObject to hold the response data, I'm putting it in a hashmap and returning the hashmap, this seems to work perfectly and ends up being roughly the same amount of code.

public HashMap get() {
     HashMap response = new HashMap();
     response.put("client", this.clientRepo.get(1));

     return response;
}

Open in new window


I still don't know why simply returning the client doesn't work.
0
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Are you sure tried it exactly as I wrote above? Make sure you had ".entity(client)" and not ".entity(client.toString)"

Anyway, it does work as expected (when you use the code that I wrote above and add the jersey-json dependency as I suggested). I just setup this quick test case and it works fine...

Client.java
package model;

public class Client {
    private int id;
    private String name;
    
    public Client() {
    }

    public Client(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

Open in new window


ClientService.java
package service;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;

import model.Client;

@Path("/client")
public class ClientService {
    
    @GET
    @Produces("application/json")
    public Response get() {
        Client client = new Client(-1, "Some company"); //this.clientRepo.get(1);
        
        return Response.status(200).entity(client).build();
    }
}

Open in new window


ClientServer.java
import com.sun.jersey.api.container.httpserver.HttpServerFactory;
import com.sun.net.httpserver.HttpServer;

public class ClientServer {
    
    public static void main(String[] args) throws Exception {
        HttpServer server = HttpServerFactory.create("http://localhost:9696/server");
        server.start();
        System.out.println("Press Enter to stop the server. ");
        System.in.read();
        server.stop(0);
    }
}

Open in new window


pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>au.com.mccarl</groupId>
    <artifactId>jersey-jax-rs-test</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-core</artifactId>
            <version>1.19</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>1.19</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-json</artifactId>
            <version>1.19</version>
        </dependency>
    </dependencies>
</project>

Open in new window



And to make it easier to test, here is the maven project that works for me...
jax-rs-test.zip
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Should have added to the above...

So then in a browser, I navigated to http://localhost:9696/server/client

and received this
{"id":-1,"name":"Some company"}

Open in new window

0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.