pyg
pyg

Reputation: 387

How do I get an int in and out of JSON with Java?

I am creating an API that will take HTTP requests and return JSON reports. I have been testing the requests in both Java (using HTTPUrlConnection) and Python (using requests). The API is written in Java Spark. I am doing some testing in Python since requests is a little easier to play with. The Python code I've used is provided for insight into what I'm trying to do, since that works.

Some of the parameters of my request are being passed as a string representation of a JSON object. What I am finding is that when a JSON object string is passed to my API and parsed, the object is treated differently depending on where it comes from, specifically when the data in question is an int.

In Python:

report_dict = {
        "client_name": "Wayne_Enterprises",
        "client_id": 123,
        "report_type": "test_report",
        "timestamp_generated": "2015-08-11T11:00:00Z",
        "report_data": {"revenue": 40000}
    }
response = requests.post(myurl, data=json.dumps(report_dict))

In Java:

JSONObject testData = new JSONObject();
JSONObject content = new JSONObject();
content.put("revenue", 40000);
testData.put("client_name","Wayne_Enterprises");
testData.put("client_id",123);
testData.put("report_type","test_report");
testData.put("timestamp_generated","2015-08-11T11:00:00Z");
testData.put("report_data",content.toString());

URL url = new URL("http","127.0.0.1",8080,"/reports/");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setUseCaches(false);
connection.setDoOutput(true);
System.out.println(testData.toString());
DataOutputStream wr = new DataOutputStream (connection.getOutputStream());
wr.writeBytes(testData.toString());
wr.close();

The JSON String is handled in the API like so:

120> JSONParser parser = new JSONParser();
121> JSONObject report = (JSONObject) parser.parse(request.body());
122> String reportType = (String) report.get("report_type");
123> String clientName = (String) report.get("client_name");
124> int clientId = (int)(long) report.get("client_id");
125> JSONObject data = (JSONObject)parser.parse((String)report.get("report_data"));
126> String dateStr = (String) report.get("timestamp_generated");

When I run the test in Python, the data is posted successfully. However, when I run the java test, I get a ClassCast Exception: java.lang.String cannot be cast to java.lang.long when I set the clientID int. Well, that's easy enough to fix. So that line now becomes:

int clientId = (int)(long) Long.parseLong((String) report.get("client_id"));

Not only is this ugly, it creates the opposite issue. Now i have 'java.lang.Long cannot be cast to java.lang.String!

Am I doing something wrong with my object creation in Java? Or am I handling the request incorrectly?

Edit: I am using org.json.simple

The string outputs: Java

{"report_data":"{\"revenue\":123}","timestamp_generated":"2000-01-01T12:00:00Z","report_type":"api_testing","client_name":"Wayne_Enterprises","client_id":123}

Python

{'client_name': 'test_client', 'report_data': '{"revenue": 4000}', 'report_type': 'transparency', 'client_id': 123, 'timestamp_generated': '2015-07-29T11:00:00Z'}

Stack Trace:

java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long
        at com.simplerelevance.Main.lambda$init$1(Main.java:124)
        at com.simplerelevance.Main$$Lambda$2/449105069.handle(Unknown Source)
        at spark.SparkBase$1.handle(SparkBase.java:311)
        at spark.webserver.MatcherFilter.doFilter(MatcherFilter.java:159)
        at spark.servlet.SparkFilter.doFilter(SparkFilter.java:131)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(Servlet
Handler.java:1652)
        at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java
:585)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.j
ava:143)
        at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.jav
a:577)
        at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandl
er.java:223)
        at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandl
er.java:1127)
        at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:
515)
        at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandle
r.java:185)
        at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandle
r.java:1061)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.j
ava:141)
        at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(Cont
extHandlerCollection.java:215)
        at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerColl
ection.java:110)
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper
.java:97)
        at org.eclipse.jetty.server.Server.handle(Server.java:497)
        at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)
        at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.jav
a:257)
        at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java
:540)
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPoo
l.java:635)
        at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool
.java:555)
        at java.lang.Thread.run(Thread.java:745)

Upvotes: 1

Views: 192

Answers (2)

Aqeel Ashiq
Aqeel Ashiq

Reputation: 2185

report.get("client_id”); will give you a String object, which cannot just be casted to long or int. Use report.getLong or report.getInt instead.

Upvotes: 1

user4979686
user4979686

Reputation:

Why not just use:

int clientId = (int) report.getLong("client_id");

The getLong returns a long based on a key. Then you cast from long to int.

Alternatively, you could change declaration of clientId in Java to type long, instead of int. Then no casting is required.

Upvotes: 2

Related Questions