playframework .json template List-Ojects with foreach? - json

My Problem is: I don't want to return the whole model object structure and datas in a json response. renderJSON() returns everything from the model in the response.
So I thought the best way would be to use *.json templates. Ok and now I have a List and I don't now how the syntax in the *.json-template must be.
Part of Controller:
List<User> users = User.find("byActive", true).fetch();
if (users != null) {
render(users);
}
"User/showAll.json" (template):
//something like foreach( User currentUser in users )
{
"username": "${currentUser.name}",
"userdescr": "${currentUser.description}"
}
For a single user it's no problem, I got it, but how does it look like for a List of users inside the json template?

There is another solution to your problem without using .json template.
"renderJSON()" has a variation takes JsonSerializer as parameter, so you can define your own serializer which implements JsonSerializer, and decide what part of model object to be sent in the response. Then you could invoke renderJSON() to return JSON object in the controller.
Example:
public class UserSerializer implements JsonSerializer<User> {
public JsonElement serialize(User src, Type typeOfSrc, JsonSerializationContext context) {
Gson gson = new GsonBuilder()
.setExclusionStrategies(new LocalExclusionStrategy()).create();
return gson.toJsonTree(src);
}
public static class LocalExclusionStrategy implements ExclusionStrategy {
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
public boolean shouldSkipField(FieldAttributes f) {
// add exlusion rules here:
// exclude all fields whose name is not "name" or "description"
return !f.getName().toLowerCase().equals("name")
&& !f.getName().toLowerCase().equals("description");
}
}
}
In your controller:
List<User> users = User.find("byActive", true).fetch();
renderJSON(users, new UserSerializer());
Play framework utilizes Google's GSON library for json serialization/deserialization
You can find more info of GSON here

[
#{list users}
{
"username": "${_.name}",
"userdescr": "${_.description}"
} #{if !_isLast},#{/if}
#{/list}
]
Check http://www.playframework.org/documentation/1.2.4/tags#list for more information

Related

ASP.NET MVC DataBinder not deserializing simple types from JSON

Input JSON:
{ "name": "gerry" }
Action method:
{ public ActionResult GenerateQrCode([FromBody] string name }
Problem:
The simple-type args are null
ModelState: Invalid
The built-in json deserializer can't handle the input in this form
I've tried:
ConfigureServices() -> services.AddControllersWithViews().AddNewtonsoftJson(); to switch to NewtonSoft, which I know/love
I've set a break-point into the non-NewtonSoft built-in MS SystemTextJsonInputFormatter.ctor() just to check, if it's still used: yes, it is, I'm not sure why, when I'm calling the above .AddNewtonsoftJson()
The situation:
The client POSTs all the input params as one JSON string document, which is UTF8 w/out BOM
The string comes in at the server-side and is nicely readable with new System.IO.StreamReader(Request.Body).ReadToEnd() from inside the immediate window
I need a way ASP.NET Core deserializes this, as it was able under the .NET4.X for many years w/out any issue
I wouldn't like to add [FromBody] and similar opt-in signatures all over the server actions/args
You pass the name as json but accept as a string so it will be null, you can use an InputFormatter like:
public class RawJsonBodyInputFormatter : InputFormatter
{
public RawJsonBodyInputFormatter()
{
this.SupportedMediaTypes.Add("application/json");
}
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
{
var request = context.HttpContext.Request;
using (var reader = new StreamReader(request.Body))
{
var content = await reader.ReadToEndAsync();
return await InputFormatterResult.SuccessAsync(content);
}
}
protected override bool CanReadType(Type type)
{
return type == typeof(string);
}
}
In startup.cs:
services
.AddMvc(options =>
{
options.InputFormatters.Insert(0, new RawJsonBodyInputFormatter());
});
And then you can get the row string
To deserilize it, you can check this, use Newtonsoft and make the string to a Model
[HttpPost]
public IActionResult GenerateQrCode([FromBody] string name)
{
object o = JsonConvert.DeserializeObject(name);
MyModel my = JsonConvert.DeserializeObject<MyModel>(o.ToString());
return View();
}

Convert data retrieved from spring-boot to JSON and fetch it in angular front-end

I want to retrieve all the skills form the skills entity in postgresql and send it using get method to the Angular front end.In HTTP request I need to send a JSON object.How can I convert the retrieved values from the postgresql to a JSON object?
I have connected the postgresql db using spring JPA. And also I get a string values to my front end. But I wanted those as JSON object
This is my controller class
#RestController
#CrossOrigin
public class SkillsController {
#Autowired
SkillsRepository skillsRepository;
#RequestMapping("/getSkills")
#GetMapping("/getSkills")
#CrossOrigin
public String getSkills(){
String result = "";
for (Skills skill : skillsRepository.findAll()){
result += skill.toString();
}
return result;
}
This is my Angular front end ts file
public getAllSkills() {
const url = 'http://localhost:8080/getSkills';
this.http.get(url, {responseType: 'text'}).subscribe(
res => {
alert(res);
},
err => {
alert('Error in retrieving');
}
);
}
I want to convert my retrieved valus in to JSON object and catch that object using get method in the front end
Spring uses Jackson serialization/deserialization by default and also the return type is Json. Instead of returning a String return type, return the object itself and it will be converted into Json without any additional code from your end. You controller would typically look as specified below.
#RestController
#CrossOrigin
public class SkillsController {
#Autowired
SkillsRepository skillsRepository;
#GetMapping("/getSkills")
public List<Skill> getSkills() {
return skillsRepository.findAll();
}
}
I will be doing some rewrite to your post. so the answer is pretty straight forward, you can simply return list from the repository and Spring will convert the list to the appriopriate JSON object or array.
#CrossOrigin
public class SkillsController {
public SkillsRepository skillsRepository;
public SkillsController(SkillsRepository _skillsRepository){
skillsRepository = _skillsRepository;
}
#RequestMapping("/getSkills")
#CrossOrigin
public List<skillEntity> getSkills(){
return (List<skillEntity>)skillsRepository.findAll();
}
}

Struts2 Convert json array to java object array - not LinkedHashmap

First off my question is very similar to below however I'm not sure if the answers are applicable to my specific problem or whether I just need clarification about how to approach it:
Convert LinkedHashMap<String,String> to an object in Java
I am using struts2 json rest plugin to convert a json array into a java array. The array is sent through an ajax post request and the java receives this data. However instead of being the object type I expect it is received as a LinkedHashmap. Which is identical to the json request in structure.
[
{advance_Or_Premium=10000, available=true},
{advance_Or_Premium=10000, available=true},
{advance_Or_Premium=10000, available=true}
]
The data is all present and correct but just in the wrong type. Ideally I want to send the data in my object type or if this is not possible convert the LinkedHashMap from a list of keys and values into the object array. Here is the class I am using, incoming data is received in the create() method:
#Namespace(value = "/rest")
public class OptionRequestAction extends MadeAbstractAction implements ModelDriven<ArrayList<OptionRequestRest>>
{
private String id;
ArrayList<OptionRequestRest> model = new ArrayList<OptionRequestRest>();
public HttpHeaders create()
{
// TODO - need to use model here but it's a LinkedHashmap
return new DefaultHttpHeaders("create");
}
public String getId()
{
return this.id;
}
public ArrayList<OptionRequestRest> getModel()
{
return this.model;
}
public ArrayList<OptionRequestRest> getOptionRequests()
{
#SuppressWarnings("unchecked")
ArrayList<OptionRequestRest> lReturn = (ArrayList<OptionRequestRest>) this.getSession().get("optionRequest");
return lReturn;
}
// Handles /option-request GET requests
public HttpHeaders index()
{
this.model = this.getOptionRequests();
return new DefaultHttpHeaders("index").lastModified(new Date());
}
public void setId(String pId)
{
this.id = pId;
}
public void setModel(ArrayList<OptionRequestRest> pModel)
{
this.model = pModel;
}
// Handles /option-request/{id} GET requests
public HttpHeaders show()
{
this.model = this.getOptionRequests();
return new DefaultHttpHeaders("show").lastModified(new Date());
}
}
One of the things which is confusing me is that this code works fine and returns the correct object type if the model is not an array. Please let me know if my question is not clear enough and needs additional information. Thanks.

Including Class name in POJO - JSON Marshalling

Following this example.
GET response is:
{
"singer":"Metallica",
"title":"Enter Sandman"
}
If more objects were included output should be like this:
[{
"singer":"Metallica",
"title":"Enter Sandman"
}, {
"singer":"Elvis",
"title":"Rock"
}]
I want to get the 'classname' written too. Something like this:
{"Track":[ {
"singer":"Metallica",
"title":"Enter Sandman"
}, {
"singer":"Elvis",
"title":"Rock"
}]}
Any simple ways to achieve this?
Looking forward to get data directly into Datatables from a JAX-RS Resteasy (Jackson) Server. Also trying to avoid DTO.
class TrackList
{
private List<Track> Track = new ArrayList<Track>();
// setter, getter
}
GET method
public TrackList getTrackInJSON() {
EDIT
GET method
public String getTrackInJSON() {
// ... create list of objects
return convertToString(objects);
}
utility method
static <T> String convertToString(List<T> list) throws IOException
{
final String json = new ObjectMapper().writeValueAsString(list);
return new StringBuilder()
.append("{\"")
.append(list.get(0).getClass().getSimpleName())
.append("\":")
.append(json)
.append("}")
.toString();
}

FlexJson deserialize object reference

I'm using Spring Roo which generated set of hibernate and FlexJSON classes.
I have entity called Location and entity called Comment.
Location has many comments (1:M).
I'm trying to generate JSON object, which will, when deserialized and inserted reference existing Location object.
When I omit location field, everything is working fine, for example:
{
"date": 1315918228639,
"comment": "Bosnia is very nice country"
}
I don't know how to reference location field.
I've tried following, but with little success:
{
"location": 10,
"date": 1315918228639,
"comment": "Bosnia is very nice country"
}
where location id is 10.
How can I reference location field in the JSON?
Edit: Added Comment entity:
#RooJavaBean
#RooToString
#RooJson
#RooEntity
public class Komentar {
private String comment;
#ManyToOne
private Location location;
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(style = "M-")
private Date date;
}
I've solved issue by adding transient property.
#Transient
public long getLocationId(){
if(location!=null)
return location.getId();
else
return -1;
}
#Transient
public void setLocationId(long id){
location = Location.findLocation(id);
}
Got similar problem, but i can't change incoming json message, so i've changed generated aspect file:
#RequestMapping(value = "/jsonArray", method = RequestMethod.POST, headers = "Accept=application/json")
public ResponseEntity<String> Komentar.createFromJsonArray(#RequestBody String json) {
for (Komentar komentar: Komentar.fromJsonArrayToProducts(json)) {
komentar.setLocation(Location.findLocation(komentar.getLocation().getId()));
komentar.persist();
}
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json");
return new ResponseEntity<String>(headers, HttpStatus.CREATED);
}
komentar.setLocation(Location.findLocation(komentar.getLocation().getId())); was added by me.
I got same problem and solved it by introducing a custom object factory.
Since JSONDeserializer expect a json object for location attribute (ex:"Location":{"id":10,..}), supplying location id as a String/Integer (ex:"Location":"10") will give you an exception.
Therefore I have written LocationObjectFactory class and telling flexjson how to deserialize a Location class object in the way I want.
public class LocationObjectFactory implements ObjectFactory {
#Override
public Object instantiate(ObjectBinder context, Object value,
Type targetType, Class targetClass) {
if(value instanceof String){
return Location.findProblem(Long.parseLong((String)value));
}
if(value instanceof Integer){
return Location.findProblem(((Integer)value).longValue());
}
else {
throw context.cannotConvertValueToTargetType(value,targetClass);
}
}
}
and deserialize the json string like this
new JSONDeserializer<Komentar>().use(null, Komentar.class).use(Location.class, new LocationObjectFactory()).deserialize(json);