How to convert HTTP Request Body into JSON Object in Java - java

I am trying find a Java lib/api that will allow me to turn the contents of a HTTP Request POST body into a JSON object.
Ideally I would like to use a Apache Sling library (as they are exposed in my container naturally).
The closest I've found it: org.apache.sling.commons.json.http which converts the header to JSON.
HTTP Post bodies are in the format; key1=value1&key2=value2&..&keyn=valueN so I assume there is something out there, but I havent been able to find it.
I may just have to use a custom JSONTokener (org.apache.sling.commons.json.JSONTokener) to do this if something doesn't already exist. Thoughts?
Thanks

Assuming you're using an HttpServlet and a JSON library like json-simple you could do something like this:
public JSONObject requestParamsToJSON(ServletRequest req) {
JSONObject jsonObj = new JSONObject();
Map<String,String[]> params = req.getParameterMap();
for (Map.Entry<String,String[]> entry : params.entrySet()) {
String v[] = entry.getValue();
Object o = (v.length == 1) ? v[0] : v;
jsonObj.put(entry.getKey(), o);
}
return jsonObj;
}
With example usage:
public void doPost(HttpServletRequest req, HttpServletResponse res) {
JSONObject jsonObj = requestParamsToJSON(req);
// Now "jsonObj" is populated with the request parameters.
// e.g. {"key1":"value1", "key2":["value2a", "value2b"], ...}
}

Jackson is also a good option - its used extensively in Spring. Here is the tutorial: http://wiki.fasterxml.com/JacksonInFiveMinutes

I recommend trying Apache Commons Beanutils.
ServeltRequest request;
Map map = request.getParameterMap();
MyObject object = new MyObject();
BeanUtils.populate(object, map);
String json = object.toJSON() //using any JSON library

Sorry on making this an own answer but obviously my reputation doesn't allow me to simply add a comment to the answer How to convert HTTP Request Body into JSON Object in Java of maerics.
I would also iterate over the request params but instead of using an arbitrary json library use the JSONObject that is provided by sling. http://sling.apache.org/apidocs/sling6/org/apache/sling/commons/json/JSONObject.html

import org.json.JSONObject;
JSONObject json = new JSONObject(request.getParameterMap())

Use Gson. With this you can create class with private variables which represent the data you want : for example.
meta:{
name:"Example"
firstname:"Example2"
}
data:[
{
title:"ecaetra"
description:"qwerty"
}
...
]
Json Object could be retrieve like this :
public class RetrieveData {
private Meta meta;
private List<Data> data;
public Meta getMeta(){
return meta;
}
public List<Data> getData(){
return data;
}
}
public class Meta {
private String name;
private String firstname;
public String getName(){
return name;
}
public String getFirstName(){
return firstname;
}
}
public class Data {
private String title;
private String description;
public String getTitle(){
return title;
}
public String getDescription(){
return description;
}
}
And your instruction are simple. Content is the content of your Page, you can retrieve it with Asynctask.
Object o = new Gson().fromJson(Content, RetrieveData.class);
data = (RetrieveData)o;
// Get Meta
data.getName(); // Example
data.getFirstName(); // Example2
// Get Data
data.get(0).getTitle(); // position 0 : ecaetra
data.get(0).getDescription(); // position 0 : qwerty

Related

Parse a JSON structure with symbol instead of a string for an attribute

I am working on an HTTP Rest query.
Wikipedia API returns a JSON. The problem is the JSON structure returned by Wikipedia.
https://en.wikipedia.org/w/api.php?action=parse&section=0&prop=text&format=json&page=pizza
This is the JSON obtained via a rest request to the Wikipedia API. To view the full JSON, you can click on the above link.
{
"parse":
{
"title":"Pizza",
"pageid":24768,
"text":{"*":"<div class=\...>"}
}
}
I would parse this using a custom deserializer which I haven't got a chance to test. Trying to parse with simple Gson like the following return null;
Result res = new Gson(str,Result.class);
I have created the classes like the following:
public class Result
{
private Parse parse;
}
public class Parse
{
private String title;
private int pageid;
private Text text;
}
public class Text{
private String *;// what should I call this attribute.
}
My plan is to add a custom deserializer like the following:
public class TextBaseDeserializer implements JsonDeserializer<Text> {
#Override
public RespondentBase deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
return jsonDeserializationContext.deserialize(jsonElement.get("*"),Text.class);
}
}
I am using Gson to parse this, like the following:
Gson tmp = new GsonBuilder().registerTypeAdapter(Text.class, new TextBaseDeserializer());
// let's assume that str is the string obtained following Rest based request from Java.
Result res = tmp.parse(str,Result.class);
I have done all the above code to handle the symbolic JSON attribute.
My question is how to parse such a JSON. In the above example, the attribute is a *
As mentioned in a comment, you should annotated field with #SerializedName("*").
You can name the field whatever you want. We'll just name it star below, but maybe all is better, since * might be a wildchar? Doesn't really matter, just choose whatever name you like.
class Text
{
#SerializedName("*")
private String star;
}
Test
String str = "{\"parse\":{\"title\":\"Pizza\",\"pageid\":24768,\"text\":{\"*\":\"<div class=\\\"mw-parser-output\\\">...</div>\"}}}";
Gson tmp = new GsonBuilder().create();
Result res = tmp.fromJson(str, Result.class);
System.out.println(res.getParse().getText().getStar());
Output
<div class="mw-parser-output">...</div>

Why this HashMap not formatted correctly in Jersey/Tomcat?

I'm testing Jersey, I wanted to mack a mock endpoint that produces this JSON object
{
"Flight1" : 757,
"Flight2" : 107,
"Flight3" : 637,
}
so I've written written this resource:
#GET
#Path("myjson")
#Produces(MediaType.APPLICATION_JSON)
public String getMyJson(#QueryParam ("test1") String lat, #QueryParam("test2") String lng) {
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("Flight 1", 765);
map.put("Flight 2", 657);
map.put("Flight 3", 908);
return map.toString();
}
But then I get this response when I call /myjson
{
Flight 1=765,
Flight 2=657,
Flight 3=908
}
Jersey already knows which element is a String and which element is an Integer, yet it format then as if they're all numbers.
Also the Json as it stands can not be formatted by the "pretty" formatter, and I believe this makes parsing it difficult by http clients.
So my question are:
Why is this happening?
How to avoid it and write simple mock JSON object for testing that is correctly formatted
You can add the Jaxb annotations to serialize and deserialize the response object directly without converting. For this you need to add the jersey's jaxb library so that when you jersey environment is getting booted, it can enable the auto conversion feature.
Example:
#Path("jaxbResource")
#Produces("application/xml")
#Consumes("application/xml")
public class UserResource {
#GET
public User[] getUserArray() {
List<User> userList = new ArrayList<User>();
userList.add(new User(1, "John"));
………
return userList.toArray(new User[userList.size()]);
}
}
#XmlRootElement
public class User {
private int id;
private String name;
public User() {}
public User(int id,String name) {
this.id = id;
this.name = name;
}
………
}
Hope this helps!!!
Why is this happening?
Because you are only making a toString of your HashMap.
Ex.
HashMap<String,String> stringStringHashMap = new HashMap<String, String>();
stringStringHashMap.put("a","b");
stringStringHashMap.put("b","b");
stringStringHashMap.put("c","b");
Will print {b=b, c=b, a=b}
How to avoid it and write simple mock JSON object for testing that is
correctly formatted
You can do this by using a lot of libraries(Gson, Jackson, JsonSimple,etc).
As this already answered what you want to make HashMap to Json
This has nothing to do with Jersey/Tomcat. For core Java programming, that is how best toString() method could process the map to String.
In order to do so you can convert to JSONObject using
String jon = JSONObject.valueToString(map);
System.out.println(jon);
OR even using the gson like
Gson gson = new Gson();
String json = gson.toJson(map);
System.out.println(json);

Parsing JSON String as simple as possible with GSON

Using GSON, how can i return a single key from a Multidimensional Json String?
Here is the Multidimensional Json String:
{"statusCode":0,"statusDescription":"OK","data":{"user":{"id":xxx,"company_id":xxx,"account_type":"5","enable_locations":true,"intuit_user_id":null,"nick_name":"xxx","is_owner":"1","enabled":"1"},"session_token":"xxx"}}
I want to return the "session_token" key value.
I'm trying this:
class app {
static class Response {
String session_token;
}
public void getSessionToken() {
String x = {"statusCode":0,"statusDescription":"OK","data":{"user":{"id":xxx,"company_id":xxx,"account_type":"5","enable_locations":true,"intuit_user_id":null,"nick_name":"xxx","is_owner":"1","enabled":"1"},"session_token":"xxx"}}
Response r = new Gson().fromJson(x, Response.class);
System.out.println(r.session_token);
}
}
But with this, my r.session_token returns null.
You would need to use Gson's JsonParser class directly and extract the data from the parse tree:
String myJsonString = "{\"name\":\"john\",\"lastname\":\"smith\"}";
JsonParser parser = new JsonParser();
JsonElement element = parser.parse(myJsonString);
JsonObject jsonObject = element.getAsJsonObject();
String lastName = jsonObject.get("lastname").getAsString();
System.out.println(lastName);
That said, it's debatable whether this would save you any real time over:
(edited from comments below):
class App {
static class Response {
String lastname;
}
public static void main(String[] args) {
String myJsonString = "{\"name\":\"john\",\"lastname\":\"smith\"}";
Response r = new Gson().fromJson(myJsonString, Response.class);
System.out.println(r.lastname);
}
}
Gson will silently ignore the fact that there's more data in the JSON than you're interested in, and later on you might be interested in it, in which case it's trivial to add fields to your Response class.
Edit due to question changing:
You have a JSON object. It contains a field data whose value is an object. Inside that object you have a field session_token that you're interested in.
Either you have to navigate to that field through the parse tree, or you have to create Java classes that all will map to. The Java classes would resemble (at the bare minimum):
class Response {
Data data;
}
class Data {
String session_token;
}

Object constructor from json or xml string

I'm working on a service that spits json everywhere. However one of the providers I consume uses XML as serialization format so I want to be able to use the same interface for parsing (and spitting out) JSON with that XML.
Problem is, I don't know of a XML type, or object that would allow me to override my constructor easily.
Hoping to clarify my point, here's some code:
public class JsonData {
private Hashtable<String, Variant> map = new Hashtable<String, Variant>();
public JsonData() {
}
public JsonData(String jsonString) {
this.deserialize(jsonString);
}
Ideally I would like a third constructor to do something like:
public JsonData(XMLString jsonString) {
this.xmldeserialize(jsonString);
}
Note how both relevant constructors take a plain string as argument.
Any pointer?
You can use static methods to create object from json or xml strings:
public static JsonData fromJson(String json) {
JsonData data = new JsonData();
data.deserializeJson(json);
return data;
}
public static JsonData fromXml(String xml) {
JsonData data = new JsonData();
data.deserializeXml(xml);
return data;
}
Can't you just check if the input is json or xml (using regex) and call appropriate method to deserialize.
Like
public JsonData(String jsonString) {
if(isValidJson(jsonString){
this.deserialize(jsonString);
} else {
this.xmldeserialize(jsonString);
}
}

Parsing/Unmarshaling query strings which passing arrays as parameters in Java

Is there a way to Parse/Unmarshall query strings which passing arrays as parameters in Java into Map or custom class?
URL example:
localhost:8080/app/ws/categories?take=10&skip=10&page=2&pageSize=10&filter[logic]=and&filter[filters][0][field]=company_id&filter[filters][0][operator]=eq&filter[filters][0][value]=1513
I need to parse filter parameter in something like this:
public class Filter {
private String logic;
private List<Filters> filters;
public class Filters {
private String field;
private String operator;
private String value;
}
}
One more point - I'm using Jersey here, maybe it has possibility to Parse/Unmarshall #QueryParam using Jersey's tools?
Anyway any other Java solutions will be OK too.
I would suggest 2 things :
Either you want to perform a GET, then to keep a RESTful approach, I would have an Url like :
localhost:8080/app/ws/categories?take/10/skip/10/page/2/pageSize/10/filter/logic/and/ ...etc
Or POST is acceptable, and I would send JSON payload
We can do it utilizing #BeanParam from JAXRS 2.0 spec
public PageableResponse<PatientBundleType> getPatientBundles(#BeanParam final PageableBeanParam paging)
{
...
}
public class PageableBeanParam
{
public PageableBeanParam(#Context final UriInfo uriInfo)
{
for (Entry<String, List<String>> param : params.entrySet())
{
String key = param.getKey();
String value = param.getValue().iterator().next();
if ("pageSize".equals(key))
{
setPageSize(Integer.valueOf(value));
}
...
}
}
}

Categories