Nested json serialization in java - java

I have a Class like so:
public class Wrapper<T>{
#JsonProperty
public Creds credentials;
public T data;
}
which, when serialized returns JSON like so:
{
"credentials" : {
"token": "xxxxx"
},
"data": {
"A": "3",
"Sub": {
"X": "something",
"Y": "something else"
}
}
}
I would like to move the contents of "data" up and return the JSON like so:
{
"credentials" : {
"token": "xxxxx"
},
"A": "3",
"Sub": {
"X": "something",
"Y": "something else"
}
}
Any pointers on how to achieve that? I've tried using the attribute below and overriding the toString on each Type of 'T', but that did not work.
#JsonSerialize(using = ToStringSerializer.class)

The solution was to add the following attribute to the "data" property.
#JsonUnwrapped

Related

Java - Spring return JSON object / array

I have a basic Rest Controller which returns a list of models in json to the client:
#RestController
public class DataControllerREST {
#Autowired
private DataService dataService;
#GetMapping("/data")
public List<Data> getData() {
return dataService.list();
}
}
Which returns data in this format:
[
{
"id": 1,
"name": "data 1",
"description": "description 1",
"active": true,
"img": "path/to/img"
},
// etc ...
]
Thats great for starting, but i thought about returning data of this format:
[
"success": true,
"count": 12,
"data": [
{
"id": 1,
"name": "data 1",
"description": "description 1",
"active": true,
"img": "path/to/img"
},
{
"id": 2,
"name": "data 2",
"description": "description 2",
"active": true,
"img": "path/to/img"
},
]
// etc ...
]
But i am not sure about this issue as i can not return any class as JSON... anybody has suggestions or advices?
Greetings and thanks!
"as i can not return any class as JSON" - says who?
In fact, that's exactly what you should do. In this case, you will want to create an outer class that contains all of the fields that you want. It would look something like this:
public class DataResponse {
private Boolean success;
private Integer count;
private List<Data> data;
<relevant getters and setters>
}
And your service code would change to something like this:
#GetMapping("/data")
public DataResponse getData() {
List<Data> results = dataService.list();
DataResponse response = new DataResponse ();
response.setSuccess(true);
response.setCount(results.size());
response.setData(results);
return response;
}

Katharsis relationship with different types?

I would like to deal with JSON that can be either:
{
"data": {
"id": "1",
"type": "permissions",
"attributes": { "permission": "VIEW" }
"relationships": {
"user": { "data": { "id": "U1", "type": "users" } }
"resource": { "data": { "id": "G1", "type": "groups" } }
}
}
}
OR
{
"data": {
"id": "1",
"type": "permissions",
"attributes": { "permission": "VIEW" }
"relationships": {
"user": { "data": { "id": "U1", "type": "users" } }
"resource": { "data": { "id": "P1", "type": "pages" } }
}
}
}
That is, I would like the "resource" relationship type to be entirely customizable ("groups" or "pages" or anything else).
Is there a way to do that with Katharsis? I was hoping for some kind of inheritance...
#JsonApiResource(type = "permissions")
public class Permission {
...
#JsonApiToOne
private SharedResource resource;
...
}
public interface SharedResource {
...
}
#JsonApiResource(type = "pages")
public class Page implements SharedResource {
...
}
But that doesn't work completely. I've finagled it enough where a findAll returns pretty well (though the links don't reflect the type "pages"), but any POST with the relationships set returns a 405 Method Not Allowed.
Not sure it's possible, but I'd really like it to be since I like Katharsis.
I think what you're referring to is polymorphic entity types. If so, this has been asked for repeatedly but currently doesn't exist.

MOXy support for JSON Pointer (RFC6901) in Jersey

I'm trying to marshal a recursive bean to JSON with MOXy in Jersey, following the specification of RFC6901 aka JSON Pointer.
E.g., I'd like to marshal this:
public class Bean {
public Integer id;
public String name;
public Bean other;
public List<Bean> next;
}
x = new Bean(123, "X");
a = new Bean(456, "A");
x.other = a;
x.next.add(x);
x.next.add(a);
into this:
{
"id": 123,
"name": "X",
"a": { "id": 456, "name": "A", "next": [ ] },
"next": [
{ "$ref": "#" },
{ "$ref": "#/a" }
]
}
and then unmarshal this JSON to the original bean. Does someone have any suggestion/solution to this problem?

How To Use Jackson's #JsonIdentityInfo for Deserialization of directed Graphs?

I want to use Jackson 2.3.3 for Deserialization/Serialization of directed graphs. The structure I came up with is roughly the following:
public Class Graph {
private final Set<Node> nodes;
public Graph(Set<Node> nodes) { ... }
public Set<Node> getNodes() { ... }
}
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "name")
public Class Node {
private final String name;
private final Set<Edge> edges;
public Node(String name, Set<Edge> edges) { ... }
public String getName() { ... }
public Set<Edge> getEdges() { ... }
}
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "name")
public Class Edge {
private final String name;
private final Node successor;
public Edge(String name, Node successor) { ... }
public String getName() { ... }
public Node getSuccessor() { ... }
}
And I expect to have this JSON-Structure:
{
"graph": [{
"name": "A",
"edges": [{
"name": "0",
"successor": "B"
}, {
"name": "1",
"successor": "A"
}]
}, {
"name": "B",
"edges": [{
"name": "0",
"successor": "A"
}, {
"name": "1",
"successor": "B"
}]
}]
}
But I get the following error while deserialization (even with annotation #JsonProperty("name") at the Getters):
com.fasterxml.jackson.databind.JsonMappingException: Invalid Object Id definition for some.package.graph.Node: can not find property with name 'name'
I have found some solutions for Jackson 1.6 with Back-Reference Annotations, but I'd like to use the new Jackson 2.x Annotation, as it was advertised so much in the API Update from 1.9 to 2.0 of Jackson.
What point am I missing here? Thanks for constructive answers in advance.
EDIT
(Removed my answer from here to the Answer section)
I got kind of blind of staring too long at it. Here's what's gone wrong:
The Serialization actually worked as intended. What didn't work was the Deserialization, because Jackson wasn't able to instantiate my Node-Object. I simply forgot to annotate the parameters of the constructor methods correctly.
I was now facing another problem. The generated JSON now looked like this:
"graph": {
"nodes": [{
"name": "B",
"edges": [{
"label": "1",
"successor": "B"
}, {
"label": "0",
"successor": {
"name": "A",
"edges": [{
"label": "1",
"successor": "A"
}, {
"label": "0",
"successor": "B"
}]
}
}]
}, "A"]
}
So far so good. But during mapping, Jackson confronts me with this Error:
java.lang.IllegalStateException: Could not resolve Object Id [B] (for [simple
type, class some.package.graph.Node]) -- unresolved forward-reference?
I even changed the Label of the edges because I thought the same property name might confuse Jackson here, but that didn't help either...
My guess here is that Jackson can't reference the Node B, because it is still being constructed (you could say it is actually some kind of root in this example). The only way to fix this seems to construct all the Nodes without the edges and inject them in a second step.

REST - How to minify Json Response

I have a JAVA REST service that returns a list of objects. Each object contains name, description, code.
I want to minify response json
{
"objects": {
"count": 10000,
"list": [
{
"name": "1",
"description": "foo",
"code": "foo",
},
{
"name": "2",
"description": "bar",
"code": "bar",
},
...... (1.000 items)
]
}
}
TO:
{
"a": {
"b": 1000,
"c": "a:objects,b:count,c:mapping,d:list,e:name,f:description,g:code",
"d": [
{
"e": "1",
"f": "foo",
"g": "foo",
},
{
"e": "2",
"f": "bar",
"g": "bar",
},
...... (1.000 items)
]
}
}
how can i do it, thanks.
Even though we don't know what specific technologies you are using. I am going to make an assumption that you are using some sort of REST library like Spring or JaxRS and you are serializing POJOs into the JSON. I will also make the assumption that you have everything setup and working for that configuration and I will focus on the output specifically using that setup.
If you are using something like Jackson for your POJO, you can add the following Annotation to your class:
public class MyResponseObject {
#JsonProperty("a")
private MyObject objects;
public MyObject getObjects() { return objects; }
public void setObjects(MyObject object) { this.objects = object; }
}
public class MyObject {
#JsonProperty("b")
private long count;
#JsonProperty("d")
private List<Item> list;
// getters/setters
}
public class Item {
#JsonProperty("e")
private Sting name;
#JsonProperty("f")
private String description;
#JsonProperty("g")
private String code;
// getters/setters
}
In regards to the mapping of what each of those mean, you can hard/code that mapping, but I don't think there is an automatic way to do that. You can also include what that mapping is in the JavaDoc for your method. Another alternative is if this is an API that is public to other services, you can not only provide documentation, but also a packaged Jar with the POJOs that your API puts out. This way all they have to do is include your jar file as a dependency and include them in the mapped classes.
I hope this helps guide you in the right direction.
Also, if you don't use Jackson, but prefer JAXB use #XmlElement(name="a")

Categories

Resources