Spring json #ResponseBody - return a named variable - json

I have a Spring controller method that is correctly returning a collection of objects in the JSON to the client:
#RequestMapping(value="/admin/rawreads/unknowntags", method=RequestMethod.GET)
public #ResponseBody Collection<RawRead> getRawReadsWithUnknownTag() {
....
}
I'm trying to integrate a jQuery addon/plugin called DataTables. DataTables can handle the asynchronous request to fetch data and populate a table in the page for me, however it requires the data to be return in an array with a specific name "aaData" rather than the current format of :
[{"oid":149452,"date":1233076733000,"readerId":"811210008","recordNo":226,"tagCode":"0103A003C0","reader":null,"guard":null,"checkpoint":null},{"oid":149453,"date":1233076734000,"readerId":"8112100 .... etc]
Suggested return format for DataTables from the DataTable docs:
{
"sEcho": 1,
"iTotalRecords": "n",
"iTotalDisplayRecords": "n",
"aaData": [
[object1][object2].... etc
]
}
How can I change my Java method to return data in the format DataTables needs - a named array?
EDIT:
Tried putting vars into a HashMap serverside, gets a bit closer to what I need:
{"iTotalDisplayRecords":3050,"iTotalRecords":3050,"aaData":
[{"oid":149452,"date":1233076733000, ...<snip>},{...}]
}

Make a separate class in the correct format for data tables, having fields for sEcho, itotalrecords, ittotaldisplayrecords and then an array called aaData.
Then return this class via jason and that is then in your suggested format.
class TableDTO
{
int sEcho;
int iTotalRecords;
int itotalDisplayRecords;
array[] aaData;
}
Obviously assign data to these fields and proper accessors etc!

You must write one more TotalDisplayRecords class and it must incluse array oid class. After that, you return TotalDisplayRecords object.

Related

DataType for exposing data as json in mvc model

how can I introduce new property into my mvc model which will hold this cities json data.
public ActionResult Edit(int id)
{
MyModel model = repository.GetById(id);
if (model.CountryId.HasValue)
{
// load cities into new property
}
return this.View(result);
}
what data type should be my property (Cities) if I want to be exposed as json on client side for further js manipulation? ICollection? Is there any recommendation for this?
Set them up as any object type you like:
MyModel model = repository.GetById(id);
if (model.CountryId.HasValue)
{
model.Cities = repository.GetCities(model.CountryId.Value);
}
return this.View(model);
Then, on the client, you can use Json.NET library to serialize it. I use this trick when I'm trying to pass an array to a client-side JS component; essentially, it serializes the array of objects into a client-side array:
#(Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.Cities))
Whatever type of object represents each city is what determines what gets rendered out to the client; it simply reads the object and renders an equivalent JS object with all the same properties. You can fine tune that by saying:
Model.Cities.Select(i => new { i.ID, i.Name, .. })
Which only includes a subset. There are also attributes you can use to exclude certain columns I believe.

How to parse json arrary?

I have come across a problem of parsing json data . I am building project using spring boot based on REST api . When i have to parse data corresponding to domain then it is very easy , i use RequestBody in controller method with domain name but in current scenerio i have a list of domain in json form :
{
"data":[
{
"type":"abc",
"subtypes":[
{
"leftValue":"BEACH",
"rightValue":"MOUNTAIN",
"preferencePoint":60
},
{
"leftValue":"ADVENTURE",
"rightValue":"LEISURE",
"preferencePoint":60
}
]
},
{
"type":"mno",
"subtypes":[
{
"leftValue":"LUXURY",
"rightValue":"FUNCTIONAL",
"preferencePoint":60
},
{
"leftValue":"SENSIBLE",
"rightValue":"AGGRESIVE",
"preferencePoint":0
}
]
}
]
}
I am sending data in list where type is the property of class Type
and class Type has list of Subtypes class and subtype class contains leftValue and rightValue as enums
I am using spring boot which uses jackson liberary by default and i want to parse this data into corresponding Type class using Jackson. Can any one provide me solution.
It wasn't clear to me if you have static or dynamic payload.
Static payload
For static one, I would personally try to simplify your payload structure. But your structure would look like this. (I skipped getters and setters. You can generate them via Lombok library).
public class Subtype{
private String leftValue;
private String rightValue;
private int preferencePoint;
}
public class Type{
private String type;
private List<Subtype> subtypes;
}
public class Data{
private List<Type> data;
}
Then in your controller you inject Data type as #RequestBody.
Dynamic payload
For dynamic payload, there is option to inject LinkedHashMap<String, Object> as #RequestBody. Where value in that map is of type Object, which can be casted into another LinkedHashMap<String, Object> and therefore this approach support also nested objects. This can support infinite nesting this way. The only downside is that you need to cast Objects into correct types based on key from the map.
BTW, with pure Spring or Spring Boot I was always able to avoid explicit call against Jackson API, therefore I don't recommend to go down that path.

Spring MVC : post request and json object with array : bad request

I'm trying to retrieve parameters from a http POST request with Spring MVC.
The request contains the following json object (content-type : application/json), which itself contains an array of customObjects :
{
"globalId":"338",
"lines":[
{
"id": "someId",
"lib":"blabla",
...
}
]
}
Here's the code I'm trying to use :
#RequestMapping(method = RequestMethod.POST, value = "/valider")
#ResponseBody
public void valider(final HttpServletRequest request, #RequestParam("globalId") final String globalId, #RequestParam("lines") final MyCustomObject[] lines) {
All I'm getting is a "bad request" error (http 400).
Is it possible to separately retrieve the two parameters "globalId" and "lines" ? Or since they are in the same json object, it has to be treated has a single parameter ? How do you proceed when you have more than one parameter in a Post request ?
I think you're looking for something like `#RequestBody. Create a class to represent your JSON data. In your case, this class will contain two member variables - globalId as a string and lines as an array of the object it represents. Then in your controller method, you will use the #RequestBody annotation on this class type so that Spring will be able to convert the JSON into object. Check the examples below.
http://www.leveluplunch.com/java/tutorials/014-post-json-to-spring-rest-webservice/
JQuery, Spring MVC #RequestBody and JSON - making it work together
http://www.techzoo.org/spring-framework/spring-mvc-requestbody-json-example.html
create model object to map your Json data
class DLibrary{
int id;
String lib;
//getters/setters
}
class GLibrary{
int globalId;
List<DLibrary> lines;
//getters/setters
}
Replace your controller code with below
#RequestMapping(method = RequestMethod.POST, value = "/valider")
#ResponseBody
public void valider(#RequestBody GLibrary gLibrary) {
#RequestBody annotation will map Json to Java Object implicitly.
To achieve this spring must require jackson-core and jackson-mapper library included in your application and your Java class should have getter and setters i.e it must follow bean standards.
Indeed, I have to use #RequestBody to get the JSON object.
Quick summary, depending on how the parameters are passed in the http POST body request :
one JSON object (Content-Type: application/json), use #RequestBody to map the json object to a java object
multiple parameters (Content-Type: application/x-www-form-urlencoded), use #RequestParam for each parameter

ASP.NET MVC 3 controller failed to receive a json 2D array

Not sure if it is a bug or not. I followed some tutorial to post a Json 2D array to a ASP.NET MVC controller, and it works fine when the first element of the array is not empty, otherwise it fails.
Example: If my json obj is
var obj = {
ItemsArr: [[1, 2],[]] // first element is an array with a few elements
};
The controller will receive the data correctly. However if the first element of the 2D array is an empty array, like:
var obj = {
ItemsArr: [[], [1, 2]] // first element is an EMPTY array
};
the controller will receive a null.
I'm using jquery.json-2.3.min.js to convert objs to json strings.
The converted strings look fine:
{"ItemsArr":[[1,2],[]]}
{"ItemsArr":[[],[1,2]]}
The model code:
public class Model
{
public List<string[]> ItemsArr {get;set;}
}
public MyController : Controller
{
public ActionResult DoSomething( Model model )
{ ...
}
}
Have anyone met this problem? Any idea to solve it?
Thanks in advance!
===================================
Edit:
After some research, if I changed the empty array to null, it works.
{"ItemsArr":[null,[1,2]]}
I would suggest passing a array of objects and create a class with the Same properties on The server side, asp.net MVC will then automatically convert this array (on the JS end) into a list (or any other IEnumerable) that is a part of the action signature.

Jackson JSON to Java mapping for same attrubute with different data type

I have a JSON object which I don't have control of and want to map it to a Java object which is pre-created.
There is one attribute in the JSON object which can be a URL or it could be a JSONArray.
Class SomeClass {
private URL items;
public URL getURL() {
return items;
}
public void setURL(URL url) {
this.items = url;
}
}
Below is the JSON:
Case A:
{
...
items: http://someurl.abc.com/linktoitems,
...
}
OR
Case B
{
...
items: [
{ "id": id1, "name": name1 },
{ "id": id2, "name": name2 }
]
...
}
If i create the POJO to map for Case A, Case B fails and vice versa. In short, is there a way to map the JSON attribute to the POJO field with different data types? In that case I will create two separate fields in the POJO named,
private URL itemLink;
private Item[] itemList;
It depends on exact details, but if what you are asking is if it is possible to map either JSON String or JSON array into a Java property, yes this can be done.
Obvious way would be to define a custom deserializer which handles both kinds of JSON input.
But it is also possible to define Java type in such a way that it can be constructed both by setting properties (which works from JSON Object) and have a single-String-arg constructor or static single-String-arg factory method marked with #JsonCreator.
Yet another possibility is to use an intermediate type that can deserialized from any JSON: both java.lang.Object and JsonNode ("JSON tree") instances can be created from any JSON. From this value you would need to do manual conversion; most likely in setter, like so:
public void setItems(JsonNode treeRoot) { .... }
What will not work, however, is defining two properties with the same name.
One thing I don't quite follow is how you would convert from List to URL though. So maybe you actually do need two separate internal fields; and setter would just assign to one of those (and getter would return value of just one).