Including Class name in POJO - JSON Marshalling - json

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();
}

Related

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();
}
}

Moshi Custom JsonAdapter

I am trying to create a custom JsonAdapter for my JSON data that would bypass the serialization of specific field. Following is my sample JSON:
{
"playlistid": 1,
"playlistrows": [
{
"rowid": 1,
"data": {
"123": "title",
"124": "audio_link"
}
}
]
}
The JSON field data in above have dynamic key numbers, so I want to bypass this data field value and return JSONObject.
I am using RxAndroid, Retrofit2 with Observables. I have created a service class:
public static <S> S createPlaylistService(Class<S> serviceClass) {
Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(baseURL)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(httpClientBuilder.build())
.addConverterFactory(MoshiConverterFactory.create());
return builder.build().create(serviceClass);
}
I am calling this service using observable like this:
#GET("http://www.mylink.com/wp-json/subgroup/{subgroupId}/playlist/{comboItemId}")
Observable<Playlist> getPlaylist(#Path("subgroupId") int subgroupId, #Path("comboItemId") int comboItemId);
Then I run it like this:
ServiceBuilder.createPlaylistService(FHService.class).getPlaylist(123, 33);
My Pojo classes look like this:
public class Playlist {
#Json(name = "playlistid")
public Long playlistid;
#Json(name = "playlistrows")
public List<Playlistrow> playlistrows = null;
}
public class Playlistrow {
#Json(name = "rowid")
public Long rowid;
#Json(name = "data")
public Object data;
}
The problem is it would return a data value in this format:
{
123=title,
124=audio_link
}
which is invalid to parse as JSONObject.
I have Googled a lot and have also checked some Moshi example recipes but I had got no idea about how to bypass this specific field and return valid JSONObject, since I am new to this Moshi library.

Jackson: deserialize JSON with XML-like lists

A service I don't control is sending me JSON that looks like this when there is one item:
{ items: {
item: { ... }
}
... like this when there is no item:
{ items: null }
... and like this when there are two or more items:
{ items: {
item: [
{ ... },
{ ... }
]
}
}
I believe this is because the service was designed to produce XML like this:
<items>
<item>....</item>
<item>....</item>
</items>
... and has thrown the results at an XML->JSON convertor without paying much attention to the result.
Using Jackson, I can handle the "sometimes null, sometimes object, sometimes array" issue in Jackson by configuring my ObjectMapper with DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY.
I can handle the two-layer structure by defining an Items class with a field List<Item> item.
However, the Items class is only there as a sop to the weird JSON format. Other than by writing a whole custom deserializer, can I persuade Jackson to deserialize to an object as if the structure was:
{ items: [ { ... }, { ... } ] }
?
It looks like you have a root object which contains Items property. In this case you can use #JsonUnwrapped annotation. See below class:
class Root {
#JsonUnwrapped
private Items items = new Items();
public Items getItems() {
return items;
}
public void setItems(Items items) {
this.items = items;
}
}
Simple usage:
ObjectMapper mapper = new ObjectMapper();
Items items = new Items();
items.setItem(Arrays.asList(new Item(), new Item()));
Root wrapper = new Root();
wrapper.setItems(items);
String json = mapper.writeValueAsString(wrapper);
System.out.println(json);
Above program prints:
{"item":[{"name":"X"},{"name":"X"}]}
Usually the easiest way to handle mapping is to reflect structure of data format in your POJO structure. So in this case, you would add one functionally unnecessary, but mapping-wise necessary, property:
public class POJO {
public ItemHolder items;
// might want convenience method for Java access, but not with getter name
public List<Item> items() {
return (items == null) ? null : items.item;
}
}
public class ItemHolder {
public List<Item> item;
}
and you do still also need to enable DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY to handle mapping from single Item into List<Item>.
But perhaps the other answer of using #JsonUnwrapped also helps; it is another option.

GXT 3.0 JsonReader with multiple root objects

I'm starting out with GXT and am a bit confused on how to use the JsonReader to parse a valid json string with multiple root objects. I have a set of selection boxes to build the sql statement to display records in a grid. I'm getting the values for the selections from the database as well. What I'm attempting to do is a single request to my php database functions to build the json with all the values for the selection boxes in one string. My first thought was the JsonReader.
Here's an example of the json I'm working with:
"categories":[{"id":"1","value":"categoryValue1"},{"id":"2","value":"categoryValue2"}], "frequencies":[{"id":"1","value":"frequencyValue1"},{"id":"2","value":"frequencyValue2"}]
Building off the cityList example in the api, this is what I've got so far.
JsonRootObject interface:
public interface JsonRootObject {
List<SelectionProperties> getCategories();
List<SelectionProperties> getFrequencies();
}
JsonRootObjectAutoBeanFactory:
public interface JsonRootObjectAutoBeanFactory extends AutoBeanFactory {
AutoBean<JsonRootObject> jsonRootObject();
}
I created a SelectionProperties interface as all are single int/string value pairs:
public interface SelectionProperties {
String getId();
String getValue();
}
Now, according to the api:
// To convert from JSON data, extend a JsonReader and override
// createReturnData to return the desired type.
So I created a reader for both categories and frequencies;
CategoryReader:
public class CategoryReader
extends
JsonReader<ListLoadResult<SelectionProperties>, JsonRootObject> {
public CategoriesReader(AutoBeanFactory factory, Class<JsonRootObject> rootBeanType) {
super(factory, rootBeanType);
}
protected ListLoadResult<SelectionProperties> createReturnData(Object loadConfig, JsonRootObject incomingData) {
return new ListLoadResultBean<SelectionProperties>(incomingData.getCategories());
}
}
FrequencyReader:
public class FrequencyReader extends
JsonReader<ListLoadResult<SelectionProperties>, net.apoplectic.testapps.client.JsonRootObject> {
public FrequencyReader(AutoBeanFactory factory, Class<JsonRootObject> rootBeanType) {
super(factory, rootBeanType);
}
protected ListLoadResult<SelectionProperties> createReturnData(Object loadConfig, JsonRootObject incomingData) {
return new ListLoadResultBean<SelectionProperties>(incomingData.getFrequencies());
}
}
This doesn't feel quite right. I'm creating multiple instances of basically the same code and parsing the actual json string twice (at this point. I may have more options for the grid once I dig in). My question is am I missing something or is there a more efficient way to parse the response string? From my onSuccessfulResponse:
JsonRootObjectAutoBeanFactory factory = GWT.create(JsonRootObjectAutoBeanFactory.class);
CategoryReader catReader = new CategoriesReader(factory, JsonRootObject.class);
FrequencyReader freqReader = new FrequenciesReader(factory, JsonRootObject.class);
categories = catReader.read(null, response);
frequencies = freqReader.read(null, response);
List<SelectionProperties> categoriesList = categories.getData();
List<SelectionProperties> frequenciesList = frequencies.getData();
ListBox cateBox = new ListBox(false);
ListBox freqBox = new ListBox(false);
for (SelectionProperties category : categoriesList )
{
cateBox.addItem(category.getValue(), category.getId());
}
for (SelectionProperties frequency : frequenciesList)
{
freqBox.addItem(frequency.getValue(), frequency.getId());
}
The above does work, both the ListBoxes are populated correctly. I just wonder if this is the correct approach. Thanks in advance!

playframework .json template List-Ojects with foreach?

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