Parse querystrings of a request as JSON - java

I'm going to receive requests with a JSON object passed as querystring which will no longer have a JSON structure, it will be something like this:
http:/mysite/api/doSomething?name=name&address=address...
I need to store it as a String following a JSON structure, the problem is that the original JSON object passed as querystring may have attributes that are collections and I can't figure out a way to parse it back correctly.
Is there a Java function or a library to achieve this easily?

I assume you are using spring mvc/jersey in controller. In that case you can do something like this
#RequestMapping(value = "/mysite/api/doSomething", method = RequestMethod.GET)
public String search(
#RequestParam Map<String,String> allRequestParams) {
JSONObject js = new JSONObject();
for (Map.Entry<String,String> entry : allRequestParams.entrySet()){
js.put(entry.getKey(), entry.getValue());
}
String jsonString = js.toString();
}
Basically get all the queryparam and construct JSONObjcet, JACKSON library will not be of much use here.

Related

How can I convert ArrayList/Set to JSON and post data using postforobject method?

I have set which contains string ["a" , "b" , "c"] , I want to POST json data like (comma seperated and one string)
Here is
JSON
{"view" : "a,b,c",
"fruits" : "apple"}
to the endpoing using Resttemplate postForObject method? I have used GSON but that is not working in my project. Are there any other alternatives?
Here is my code
private run(set<data> datas) {
Set<string> stack = new hashset<>();
iterator<data> itr = datas.iterator();
while (itr.hasnext()) {
data macro = itr.next();
if (//some condition) {
stack.add(macro);
}
}
}
}
Resttemplate.getmessageconverters().add(stringconvertor);
String result = resttemplate.postforobject(endpoint, request, String.class);
}
If the data is in a specific class like format, you could go with the POJO approach that is encouraged by Spring Boot. But looking at your example, it seems like you want to achieve a one time JSON Object response.
import org.json.simple.JSONObject;
public static void run(set<data> datas, string endpoint){
// build your 'stack' set
String joined = String.join(",", stack);
JSONObject obj=new JSONObject();
obj.put("view",joined);
obj.put("fruits","apple");
//return the jsonObject as the response to your entrypoint using your method
}
You could also try the following if you use #ResponseBody annotation in Spring Boot that will convert the Response Body to the appropriate (JSON) format.
HashMap<String, String> map = new HashMap<>();
map.put("view", joined);
map.put("fruits", "apple");
return map;

Parsing a RequestBody to params

I have a code which gets a body POST from Postman:
#RequestMapping(value="/dep", method=RequestMethod.POST)
public JsonResponse dep(#RequestBody String body) throws SQLException {
Connection connection = ConnectionSingleton.getInstance().getConnection(env);
Statement statement = connection.createStatement();
statement.close();
connection.close();
System.out.println("BODY #### "+body);
return new JsonResponse("depreciated");
}
Postman sent:
{
"idn":"MLCM00292",
"monto":"9149.92"
}
And the string is like:
%7B%0A%09%22idn%22%3A%22MLCM00292%22%2C%0A%09%22monto%22%3A%229149.92%22%0A%7D=
The words in bold are the parameters and their assigned values. I want to receive the parameters like variable. What its the correct way to get the params from a body in a POST request? What is missing in my code?
You can use a Map like this:
public JsonResponse dep(#RequestBody Map<String, String> body)
and then inside the method get the values like this:
String id = body.get("idn");
String monto = body.get("monto");
You can change the generics type for the Map class as it fits your needs. For example, if you are going to receive values of different types you can use it like Map<String, Object> body, then you could parse every value according to the data type (which you must know in advance). Something like:
String id = body.get("idn").toString();
double monto = Double.parseDouble(body.get("monto").toString());
For more complex data type I recommend you to create some custom POJOs or JavaBeans.
Further readings
Difference between DTO, VO, POJO, JavaBeans?

Convert JSON String to JSON object to get Values

I am getting a JSON string and want to print Name values on the console via JSP. Can someone suggest how to do it?
String AllCustomLockingCriterias = '{"TemplateArray":[{"Id":16,"Name":"Machine","type":"PM"},
{"Id":17,"Name":"Ethernet","type":"PM"},
{"Id":18,"Name":"Hard Disk","type":"PM"}]}';
Output I need:
Machine
Ethernet
Hard Disc
I want to start a loop and my output will be:
Machine
Ethernet
Hard Disc
use Gson jar package(produced by google.com) , FastJson(produced by alibaba.com) or jackson to serialize or deserialize the json string and the Class object.One jar package is enough.
use maven pom dependency/gradle config to add the gson to your project or add the gson jar into your lib folder directly,it is all up to you, maven is preferred.
define the Java Class field member,with the meta info from your json string,such as 'id','name','type'.The Java Class can be named 'Template'(do not forget to implement the java Serializable interface).
code example:
Gson gson = new Gson();
TypeToken typeToken = new TypeToken<List<Template>>() {};
Type type = typeToken.getType();
List<Template> templates = gson.fromJson(json, type);
return the templates list to the front jsp page within the jsp page scope.
if you user springMVC framework,you can add a model param to the method params,
#RequestMapping(value = "/test",method = RequestMethod.GET)
public String test(Model model){
model.addAttribute("templates",templates);
return "jspFileName";
}
for jsp site,you can use jsp EL Express to show the list
<c:forEach items="${templates}" var = "template">
${template.name}
</c:forEach>
the last but the most easy method is ,you can pass the json string to the jsp page.on the other words,do not need to serialize the json string to class,just pass the string to the jsp with the model attribute provided by springMVC or even the basic Servlet.And then use the javascript method to handle the json string.for example,
var obj = JSON.parse(json);
var array = obj.TemplateArray;
array.foreach(function(item) {
console.log(item.name);
});
"fasterxml" or "jackson" has Java library that is able to transform your JSON string to a TreeNode. You can then access various fields.
#Test
public void test() throws IOException {
String AllCustomLockingCriterias = "{\"TemplateArray\":[{\"Id\":16,\"Name\":\"Machine\",\"type\":\"PM\"},\n" +
" {\"Id\":17,\"Name\":\"Ethernet\",\"type\":\"PM\"},\n" +
" {\"Id\":18,\"Name\":\"Hard Disk\",\"type\":\"PM\"}]}";
//create mapper to map JSON string to handy Java object
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = objectMapper.readValue(AllCustomLockingCriterias,JsonNode.class);
//fetch value that has field name "TemplateArray"
JsonNode templateArray = rootNode.get("TemplateArray");
//loop over the values in the TemplateArray and extract Name, if present.
for(JsonNode subNode : templateArray){
if(subNode.has("Name")){
System.out.println(subNode.get("Name"));
}
}
}
Use JsonNode with JPointer.
Example:
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readValue(
"{\"TemplateArray\":[{\"Id\":16,\"Name\":\"Machine\",\"type\":\"PM\"}, {\"Id\":17,\"Name\":\"Ethernet\",\"type\":\"PM\"},{\"Id\":18,\"Name\":\"Hard Disk\",\"type\":\"PM\"}]}",
JsonNode.class);
node.at("/TemplateArray").forEach(a -> System.out.println(a.at("/Name")));
Prints:
"Machine"
"Ethernet"
"Hard Disk"

Rest Assured - deserialize Response JSON as List<POJO>

I have a POJO Artwork. I'm retrieving a List of those objects from a RESTful webservice in the HTTP response body in JSON format. I'm trying to write a Rest Assured-based test that would analyze the returned list. The code looks like this:
Response response = get("/artwork");
List returnedArtworks = response.getBody().as(List.class)
The problem is, I can't get Rest Assured to parse the returned JSON as List<Artwork>. Instead, I get a List<LinkedHashMap>. The map has a proper structure, i.e. could be mapped by Jackson to Artwork object, but I'd like to avoid mapping it manually.
JSON mappings in my model are OK, because when I map single object like this:
Artwork returnedArtwork = response.getBody().as(Artwork.class);
it works fine.
Is it possible to get returnedArtworks as List<Artwork>?
You can do this:
List<Artwork> returnedArtworks = Arrays.asList(response.getBody().as(Artwork[].class));
The trick is to deserialize JSON to an array of objects (because there is no difference between the JSON string of an array or a list), then convert the array to a list.
this solution works for version 3.0.2 (io.restassured):
JsonPath jsonPath = RestAssured.given()
.when()
.get("/order")
.then()
.assertThat()
.statusCode(Response.Status.OK.getStatusCode())
.assertThat()
.extract().body().jsonPath();
List<Order> orders = jsonPath.getList("", Order.class);
This will extract the objects for a structure like this:
public class Order {
private String id;
public String getId(){
return id; }
public void setId(String id){
this.id = id;
}
}
with the given json:
[
{ "id" : "5" },
{ "id" : "6" }
]
By using Google's Gson library you can easily parse it to List<Artwork>. Try below code
Gson gson = new Gson();
List<Artwork> returnedArtworks = gson.fromJson(jsonStr, new TypeToken<List<Artwork>>(){}.getType());
//* where jsonStr is the response string(Json) receiving from your Restful webservice
Rest-assured provide an as(java.lang.reflect.Type) next to the version expecting a Class used in the question.
java.lang.reflect.Type type; //TODO defines the type.
Response response = get("/artwork");
List<Artwork> returnedArtworks = response.getBody().as(type)
In my opinion the way the type variable depends from the serialization lib that is used.
If using Gson, as pointed out by Purushotham's answer, TypeToken can be used. I prefer using it directly in rest-assured:
Type type = new TypeToken<List<Artwork>>(){}.getType();
Response response = get("/artwork");
List<Artwork> returnedArtworks = response.getBody().as(type)
When using Jackson, the solution is to use the TypeFactory (javadoc, source) to tell to which type it should be de-serialized:
Type type = TypeFactory.defaultInstance().constructCollectionLikeType(ArrayList.class, Artwork.class);
Response response = get("/artwork");
List<Artwork> returnedArtworks = response.getBody().as(type)
With REST assured 3.0.2 you can simply check if content exists in the array
when().get("/artwork").then().body("artworks", hasItem("some art");
//or check multiple values in array
when().get("/artwork").then().body("artworks", hasItems("some art", "other art");
This way you will avoid complexity in your code by converting JSON to list more examples how to check response content can be found link

How to convert map of JSON objects to JSON using GSON in Java?

I have a map of JSON objects as follows:
Map<String,Object> map = HashMap<String,Object>();
map.put("first_name", "prod");
JSONObject jsonObj = new JSONObject("some complex json string here");
map.put("data", jsonObj);
Gson gson = new Gson();
String result = gson.toJson(map);
Now if the "some complex JSON string here" was:
{"sender":{"id":"test test"},"recipients":{"id":"test1 test1"} }
and execute above code gives me something like:
{
"first_name": "prod",
"data": {
"map": {
"sender": {
"map": {
"id": "test test"
}
}
},
"recipients": {
"map": {
"id": "test1 test1"
}
}
}
}
}
I might have some syntax error up there, but basically I don't know why I am seeing objects wrapped around map's.
Update
according to comments, it is a bad idea to mix different json parsers.
i can understand that. but my case requires calling an external api which takes a hash map of objects that are deserialized using gson eventually.
is there any other object bedsides JSONObject that i can add to the map and still have gson create json out of it without extra 'map' structure? i do understand that i can create java beans and achieve this. but i'm looking for a simpler way since my data structure can be complex.
Update2
going one step back, i am given a xml string. and i have converted them to json object.
now i have to use an external api that takes a map which in turn gets converted to json string using gson in external service.
so i am given an xml data structure, but i need to pass a map to that function. the way i have described above produces extra 'map' structures when converted to json string using gson. i do not have control to change how the external service behaves (e.g. using gson to convert the map).
Mixing classes from two different JSON libraries will end in nothing but tears. And that's your issue; JSONObject is not part of Gson. In addition, trying to mix Java data structures with a library's parse tree representations is also a bad idea; conceptually an object in JSON is a map.
If you're going to use Gson, either use all Java objects and let Gson convert them, or use the classes from Gson:
JsonObject root = new JsonObject();
root.addProperty("first_name", "prod");
JsonElement element = new JsonParser().parse(complexJsonString);
root.addProperty("data", element);
String json = new Gson().toJson(root);
This has to do with the internal implementation of JSONObject. The class itself has an instance field of type java.util.Map with the name map.
When you parse the String
{"sender":{"id":"test test"},"recipients":{"id":"test1 test1"} }
with JSONObject, you actually have 1 root JSONObject, two nested JSONObjects, one with name sender and one with name recipients.
The hierarchy is basically like so
JSONObject.map ->
"sender" ->
JSONObject.map ->
"id" -> "test test",
"recipients" ->
JSONObject.map ->
"id" -> "test test1"
Gson serializes your objects by mapping each field value to the field name.
Listen to this man.
And this one.
I'd a similar problem and I finally resolved it using json-simple.
HashMap<String, Object> object = new HashMap<String,Object>;
// Add some values ...
// And finally convert it
String objectStr = JSONValue.toJSONString(object);
You may try out the standard implementation of the Java API for JSON processing which is part of J2EE.
JsonObject obj = Json
.createObjectBuilder()
.add("first_name", "prod")
.add("data", Json.createObjectBuilder()
.add("sender", Json.createObjectBuilder().add("id", "test test"))
.add("recipients", Json.createObjectBuilder().add("id", "test1 test1"))).build();
Map<String, Object> prop = new HashMap<String, Object>() {
{
put(JsonGenerator.PRETTY_PRINTING, true);
}
};
JsonWriter writer = Json.createWriterFactory(prop).createWriter(System.out);
writer.writeObject(obj);
writer.close();
The output should be:
{
"first_name":"prod",
"data":{
"sender":{
"id":"test test"
},
"recipients":{
"id":"test1 test1"
}
}
}

Categories

Resources