Deserialize Retrofit2 response into JSON without Jackson - java

I am calling an API using Retrofit2 that is giving me a large and complicated response. This was fine since all I needed to do was deserialize the response into a String and then put it on an activeMQ.
However, now I would like to add two more Json attributes to the complicated response so that it looks like the following:
{
"event": "some event",
"link": "some link",
"details": {complicated response ...}
}
How do I deserialize a response as a Json (javax.json.Json), so then I can build onto it as a JsonObject with the new attributes, and then a String?
The JacksonConverterFactory forces me to fit this complicated response into POJOs and I do not want to do that! Right now I am adding strings to the top of the response, but this is not an ideal solution.

Assuming that your large and complicated response is in a string named input, you could perhaps do the following:
JsonReader reader = Json.createReader(new StringReader(input));
JsonObject response = reader.readObject();
JsonObject queueMessage =
Json.createObjectBuilder()
.add("event", "some event")
.add("link", "some link")
.add("details", response)
.build();
Another approach, which uses Jackson and doesn't force you to deserialize the complicated response into a structure of JSON-objects, is to use the #JsonRawValue annotation, which lets you mark a String field as already containing JSON that should be included verbatim during serialization.
This allows you to do something like:
public class MQMessage {
public String event, link;
#JsonRawValue
public String details;
}
MQMessage message = new MQMessage();
message.event = "some event";
message.link = "Some link";
message.details = input;
String forMQ = new ObjectMapper().writeValueAsString(message);
Be aware that Jackson doesn't do any verification that details actually contains valid JSON.

Related

Is there a better way to Optimize code that takes one value out of a Request body, the data comes in, in json format

I have an request object, that contains a huge amount of data. But there is a filter in my code, where I need to take out just one element. At the moment I am Deserializing the whole object, which seems overkill to just get one element
This is part of a zuul filter
import com.netflix.zuul.context.RequestContext;
RequestContext ct = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
ObjectMapper mapper = new ObjectMapper();
ServletInputStream stream = null;
try {
stream = request.getInputStream();
GetPageRequest page = mapper.readValue(stream,GetPageRequest.class);
log.info("URL IN BODY "+page.getUrl());
It seems over kill to deserialize an entire object to get one element but I cant think of a more efficient and optomized way
At it's simplest the request payload can just be a string so you could read the input as a string and then parse what you want out using a regular expression or an indexOf or whatever suits best?
With thanks to everyone. I created this method. Streamed inputstream into a string Created a JSONObject which takes in and tokenizies the string
private String getURLFromRequest(ServletInputStream stream) throws IOException, JSONException {
String requestStr = IOUtils.toString(stream, "UTF-8");
JSONObject jsonObj = new JSONObject(requestStr);
return (String) jsonObj.get("url");
}

Java Array response instead of brackets

I am trying to parse a JSON response in Java but am facing difficulty due to the response being array format, not object. I, first, referenced the this link but couldn't find a solution for parsing the JSON properly. Instead, I am receiving this error when trying to display the parsed data...
Exception in thread "main" org.json.JSONException: JSONObject["cardBackId"] not found.
Snippet for displaying data:
JSONObject obj = new JSONObject(response);
JSONArray cardBackId = (JSONArray) obj.get("cardBackId");
System.out.println(cardBackId);
Data response via Postman:
[
{
"cardBackId": "0",
"name": "Classic",
"description": "The only card back you'll ever need.",
"source": "startup",
"sourceDescription": "Default",
"enabled": true,
"img": "http://wow.zamimg.com/images/hearthstone/backs/original/Card_Back_Default.png",
"imgAnimated": "http://wow.zamimg.com/images/hearthstone/backs/animated/Card_Back_Default.gif",
"sortCategory": "1",
"sortOrder": "1",
"locale": "enUS"
},
While without JSONObject I am pulling the data fine in Java and verified by using response.toString in STDOUT, this is my first time using json library in Java and it is important I parse this data as json. Any advice with this is helpful.
The response is an array and not object itself, try this:
JSONObject obj = new JSONArray(response).getJSONObject(0);
String cardBackId = obj.getString("cardBackId");
Here is the output, along with relevant files used:
First parse the response as JsonArray, instead of JsonObject.
Get JsonObject by iterating through the array.
Now get the value using the key.
Look at this example using Gson library, where you need to define the Datatype to define how to parse the JSON.
The key part of the example is: Data[] data = gson.fromJson(json, Data[].class);
package foo.bar;
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
public class Main {
private class Data {
long cardBackId;
String name;
}
public static void main(String[] args) throws FileNotFoundException {
// reading the data from a file
BufferedReader reader = new BufferedReader(new FileReader("data.json"));
StringBuffer buffer = new StringBuffer();
reader.lines().forEach(line -> buffer.append(line));
String json = buffer.toString();
// parse the json array
Gson gson = new Gson();
Data[] data = gson.fromJson(json, Data[].class);
for (Data item : data) {
System.out.println("data=" + item.name);
}
}
}

Converting a string in JSON object and validating

I am trying to validate this string below. Actually I am receiving this string in my servlet, now I need to validate these values at backend. What is the right way to do so. Shall I first convert it to JSON Object then to HashMap? Please suggest the correct/appropriate approach to be used here. I am quite new to Java and JSON.
String is
"{"if_ack":4},{"if_cmd":1,"if_state":1},{"if_cmd":1,"if_state":5}"
I am using GSON for processing JSON at server. For example:
InputStream is (send by client, JSON format)
Reader reader = new InputStreamReader(is);
Gson gson = new Gson();
List<YourClass> items = gson.fromJson(reader, new TypeToken<List<YourClass>>()
YourClass should have attributes like if_ack, if_state, if_cmd,...
Then you use as simple as this:
for (YourClass item : items) {
//do whatever you want
}
EDIT: your string should be in correct JSON format like this (JSON array): [{"if_ack":4}, {"if_cmd":1,"if_state":1}, {"if_cmd":1,"if_state":5}]
EXAMPLE:
You have JSON like this : [{"id": "1", "image": "test1"}, {"id": "2", "image": "test2"}]
YourClass.java should be:
public class YourClass{
private int id;
private String image;
//+ constructor, getters, setters,...
}
On server you can receive JSON from client side by InputStream is:
Reader reader = new InputStreamReader(is, "UTF-8");
Gson gson = new Gson();
List<YourClass> items = gson.fromJson(reader, new TypeToken<List<YourClass>>();
and then:
for (YourClass item: items){
//acces to item properties like item.id, item.image
}

How to have each record of JSON on a separate line?

When I use JSONArray and JSONObject to generate a JSON, whole JSON will be generated in one line. How can I have each record on a separate line?
It generates like this:
[{"key1":"value1","key2":"value2"}]
I need it to be like following:
[{
"key1":"value1",
"key2":"value2"
}]
You can use Pretty Print JSON Output (Jackson).
Bellow are some examples
Convert Object and print its output in JSON format.
User user = new User();
//...set user data
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(user));
Pretty Print JSON String
String test = "{\"age\":29,\"messages\":[\"msg 1\",\"msg 2\",\"msg 3\"],\"name\":\"myname\"}";
Object json = mapper.readValue(test, Object.class);
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(json));
Reference : http://www.mkyong.com/java/how-to-enable-pretty-print-json-output-jackson/
You may use of the google-gson library for beautifying your JSON string.
You can download the library from here
Sample code :
Gson gson = new GsonBuilder().setPrettyPrinting().create();
JsonParser jp = new JsonParser();
JsonElement je = jp.parse(uglyJSONString);
String prettyJsonString = gson.toJson(je);
OR
you can use org.json
Sample code :
JSONTokener tokener = new JSONTokener(uglyJsonString); //tokenize the ugly JSON string
JSONObject finalResult = new JSONObject(tokener); // convert it to JSON object
System.out.println(finalResult.toString(4)); // To string method prints it with specified indentation.
Refer answer from this post :
Pretty-Print JSON in Java
The JSON.stringify method supported by many modern browsers (including IE8) can output a beautified JSON string:
JSON.stringify(jsObj, null, "\t"); // stringify with tabs inserted at each level
JSON.stringify(jsObj, null, 4); // stringify with 4 spaces at each level
and please refer this : https://stackoverflow.com/a/2614874/3164682
you can also beautify your string online here.. http://codebeautify.org/jsonviewer
For gettting a easy to read json file you can configure the ObjectMapper to Indent using the following:
objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);

cant convert json string to regular string array in java

iam trying to convert this json string back to an array but i can't seem to do it
["\"abba\"","\"repaper\"","\"minim\"","\"radar\"","\"murdrum\"","\"malayalam
\"","\"turrut\"","\"navan\""]
can anyone help, or point me in the right direction of some tutorials. Ive tried split(",") etc but im really not too sure how to extract the words themselves.
client code:
Gson gson;
String[] words = { "hello", "Abba", "repaper", "Minim", "radar",
"murdrum", "malayalam", "cheese", "turrut","Navan" };
gson = new Gson();
String json = gson.toJson(words);
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource service = client
.resource("http://localhost:8090/RestSampleApp/rest/webservice/returnarray");
ClientResponse response = service.type(MediaType.APPLICATION_JSON)
.post(ClientResponse.class, json);
String output = response.getEntity(String.class);
//String target2 = gson.fromJson(json, String.class);
System.out.println(output);
webservice code:
#POST
#Path("returnarray")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public String returnstuff(String list) {
list2 = list.substring(1, list.length() - 1); //gets rid of "[]"
temp = new ArrayList<String>(Arrays.asList(list2.split(",")));
Algorithim algo = new Algorithim(temp); // instance of algorithim class takes in arrayList
algo.getpalindromesarray(); //creates plaindrome arraylist
newlist = algo.getnewlist();
String details = gson.toJson(newlist);
return details;
}
EDIT: My previous answer wasn't correct, see this new one...
You are not using Gson correctly... You are serializing the objects well, but you're not doing a correct deserialization... I suggest you to take a brief look to Gson documentation, it's few lines and you'll understand it better...
First you serialize your array correctly in your client, with:
String json = gson.toJson(words);
Then you send it using Jersey API, I think that it's correct (although I'm not an expert in Jersey...)
Then your problem is that you are not deserializing the JSON correctly in your web service. You should parse the JSON string passed as a parameter, and you can do it with Gson as well, like this:
Gson gson = new Gson();
Type listOfStringsType = new TypeToken<List<String>>() {}.getType();
List<String> parsedList = gson.fromJson(list, listOfStringsType);
Now you can do whatever you want with your list of words working with a proper Java List.
Once you finish your work, you serialize again the List to return it, with:
String details = gson.toJson(parsedList);
Now you have to repeat the deserializing operation in your client to parse the response and get again a List<String>...
Note: You should never try to do things like serialize/deserialize JSON (or XML...) manually. A manual solution may work fine in a particular situation, but it can't be easily adapted to changes, thus, if your JSON responses change, even only slightly, you'll have to change a lot of code... Always use libraries for this kind of things!
You'd better use json library, e.g. Jackson. If code yourself, you can do like below:
// 1st: remove [ and ]
s=s.substring(1, s.length()-1);
// 2nd: remove "
s=s.replaceAll("\"\"", "");
// 3rd: split
String[] parts = s.split(",");
You can try to use String.format to specify the format you waant to pass as part of your request.
For Ex :
WebResource webResource = client.resource("http://localhost:8090/RestSampleApp/rest/webservice/returnarray");
String input = String.format("{\manual format "}",parameter);
ClientResponse response = webResource.type("application/json").post(ClientResponse.class, input);
This is how I have acheived my goal

Categories

Resources