How to move several params to another node in jackson? - java

I have to generate strange json from object(with jackson ObjectMapper), something like:
{
"data":{
"id":"1",
"name":"Json"
},
"userType":"MD"
}
But, with jackson data-bind i can do only:
{
"id":"1",
"name":"Json",
"userType":"MD"
}
With User.class:
public class User {
private String id;
private String name;
private String userType;
//Getters Setters Constructor
I found two ways of bypassing. First one - to use another "superclass":
public class Data {
#JsonProperty("data")
private User user;
private String userType;
//Getters Setters Constructor
Second way - to use Map:
Map<String, Object> map = new HashMap<>();
map.put("data", user);
map.put("userType", "MD");
String json = objMapper.writeValueAsString(map);
But i think, that it's not idea to use this ways if i have about 8 different objects with such structure. So, what's best pratice? Or maybe there are another built in ways?
I want to find the best one

The first approach you mentioned is the best practice, but it is called Composition (HAS-A relationship) rather 'superclass' and just to add readability, you can refactor your classes like this:
public class User {
private Data data;
private String userType;
//Getters Setters Constructor
}
public class Data {
private String id;
private String name;
// getters and setters
}
So, when you marshal your pojo to json, structure will be:
{
"data":{
"id":"1",
"name":"Json"
},
"userType":"MD"
}
which is what you want! Happy coding :)
Update: If you are generating your API documentation with Swagger or Open API Spec, then there is no way to have a representation of your model if you use Map or HashMap. So, obviously, the first approach is the one you should consider!

Related

How to deserialize a list to a map using fastmap

I have a JSON that has a list of objects inside another object, something like:
{
"name":"name",
"processes":[
{
"id":123,
"desc":"main"
},
{
"id":456,
"desc":"secondary"
}
]
}
I want to parse fastjson to something like:
public class Idea {
private String name;
private Map<String, List<Process>> processes;
//Getters and setters
}
and
public class Process {
private String id;
private String desc;
//Getters and setters
}
Basically, the idea is to map that list from the JSON to a map where the key is something like Processes and the values are the list got from the JSON.
Any idea on how I could do it?

Using Spring #RequestBody to convert JSON with mixed convention in payload to Entity Object

I am using Spring #RequestBody to map a JSON payload to a Java Object. Unfortunately this JSON payload does not use a set convention but rather has names that use both camelCase and snake_case.
To be clear my Controller looks like this:
#RequestMapping(value="/mobile/device", method = RequestMethod.PUT)
public ResponseEntity<Object> flagDevice (#RequestBody List<MobileDeviceData> deviceInfoList) {
... code here ...
}
with the MobileDeviceData Entity object having several setter methods like:
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public void setFlagId(int flagId) {
this.flagId = flagId;
}
This works great and without any extra effort when the JSON objects name is camelCase. However for snake_case names I need to add the Annotation:
#JsonProperty("flag_id")
private int flagId;
in order for it to be picked up.
I know it's not a good idea to use the #JsonProperty if it can be avoided as you then will need to annotate every parameter. My question is, is there a more general way to enforce matching snake_case with the corresponding camelCase in the Entity object? And obviously to do it without screwing up the ones that are already camelCase.
As per the article here, there is a simple approach to deserialize the MobileDeviceData class. Here is the sample code as below:
#JsonDeserialize(using = UserDeserializer.class)
public class User {
private ObjectId id;
private String username;
private String password;
public User(ObjectId id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
public ObjectId getId() { return id; }
public String getUsername() { return username; }
public String getPassword() { return password; }
}
Assume User is the class we’re interested in writing the Deserializer for. Not much is notable here, except for the annotations that tell Jackson who knows how deserialize this class.
public class UserDeserializer extends JsonDeserializer {
#Override
public User deserialize(JsonParser jsonParser,
DeserializationContext deserializationContext) throws IOException {
ObjectCodec oc = jsonParser.getCodec();
JsonNode node = oc.readTree(jsonParser);
return new User(null,
node.get("username").getTextValue(),
node.get("password").getTextValue());
}
}
The deserializer is created by extending Jackson’s abstract JsonDeserializer class, and giving it the type we want to deserialize to. Difficult is figuring out that you can reference the JSON by field name with the JsonParser's ObjectCodec.
I hope it helps.
Please feel free to comment if needed!
Having been working on this a bit, I now realize doing anything like what was requested would be counterproductive.
When you receive (deserialize) a JSON Object, it is generally expected that you will deliver (serialize) with the same parameters. If an implementation extracted both camelCase and underscore parameters the same way, then it would not know how to deserialize correctly later on. By following a standard convention and then using #JsonProperty for all the exceptions, it remains possible to deserialize and later deliver the JSON object just as it was received.

Gson POJO mapping loses custom field value

I'm trying to use Gson to map JSON to POJO where the POJO contains a custom field that is not part of JSON. The field gets updated when the setters of other fields are invoked to add the names of the fields that are being updated to a list.
The POJO class looks something like this:
public class myPojo {
private List<String> dirtyFields;
private String id;
private String subject;
private String title;
public myPojo() {
dirtyFields = new ArrayList<String>();
}
public getId() {
return id;
}
public setId(String id) {
this.id = id;
}
public getSubject() {
return subject;
}
public setSubject(String subject) {
this.subject = subject;
dirtyFields.add("subject");
}
// more setter/getters
}
The dirtyFields ivar is not a deserialized field but it is used to keep track of the fields that are being updated.
After mapping, however, the list seems to become an empty list. This was not the case with Jackson.
Is this due to the expected Gson behaviour?
Gson does not call setter/getters during deserialization/serialization. It access, instead, directly to fields (even if private/protected) using reflection. This explains why your dirtyFields ivar is empty.
The possibility of calling setter/getters is not implemented in Gson as far as I know. The reason why Gson acts like this is explained better here. A comparison between Jackson and Gson features can be found here, you may be interested in setter/getter part.
However Gson is quite flexible to add a custom behavior to get what you need, you should start reading Read and write Json properties using methods (ie. getters & setters) bug
Another way to calculate your dirtyFields list could be using reflection and checking if every field of your POJO is null or not. You could start from this.

How to Dynamically generate and retrieve JSON in Java code?

I have a use case where we have to send different JSONs to different servers.
The difference is only between JSON keys, the meaning the keys carry is same and so is the data.
For example server XYZ wants JSON data to be sent in this format:
{ "firstName":"Sam", "lastName":"Jones"}
Now server ABC wants JSON data to be sent in this format:
{ "fName":"Sam", "lName":"Jones"}
And firstName and lastName data is populated via a POJO.
So, How do I achieve this? I do not want to clutter the code with if-else conditions.
But wnat to have something which would work like a template loaded dynamically and create the JSON data and also retrieve it back to the POJO.
You should create two POJOs. One for each server. Each POJO can have different property names to satisfy each of the server's requirements.
Or the POJOs can have the same property names, but be annotated to generate different JSON properties. A JSON library like Jackson can do this using the JsonProperty annotation.
How about this strategy?
1. Defines the interface to be used as a common..
interface People{
public String getRegularFirstName();
public String getRegularLastName();
}
2. Define each POJO with implemented interface
//class for "{ "firstName":"Sam", "lastName":"Jones"}"
class PeopleData2 implements People{
private String firstName;
private String lastName;
public String getRegularFirstName(){
return firstName;
}
public String getRegularLastName(){
return lastName;
}
//getter setter here..
}
//class for "{ "fName":"Sam", "lName":"Jones"}"
class PeopleData1 implements People{
private String fName;
private String lName;
public String getRegularFirstName(){
return fName;
}
public String getRegularLastName(){
return lName;
}
//getter setter here..
}
3. Make each json format deserved each POJO classes..
It is not dinamically strategy because it need to add class whe new format comes up.
but it will help system scalability

Convert object that contains another object to json

I need to pass data from HTML to Service using JSON (in JS/JQUERY)
In the service I have a service call that reciving an object that contains another object and 2 more fields.
Role object:
import java.io.Serializable;
public class Role implements Serializable {
private long id;
private String name;
}
User object:
import java.io.Serializable;
public class User implements Serializable {
private String userName;
private String password;
private ArrayList<Role> roles;
}
Till now I managed to pass data to JSON like that to other service: (data that contains only 2 parameters: id and userName )
xmlHttp.open("POST", "http://www.foo.com/serviceFunction2", true);
xmlHttp.send('{"Id": "123", "userName": "test"}');
So, my question is how can I fill the User object that contains the Role object using JS/JQUERY? like I managed to send it with this line:
xmlHttp.send('{"Id": "123", "userName": "test"}');
Thanks
There are several ways to "nest" objects in JS, but for your purpose probably the simplest is to nest your object and/or array literals. If "roles" is supposed to be an array, then something like this:
'{"userName":"test", "password":"secret", "roles":["role1","role2","role3"]}'
If each role in the array is itself an object with properties:
{
"userName":"test",
"password":"secret",
"roles": [
{ "roleName":"role1", "prop2":"someValue", "prop3":"whatever" },
{ "roleName":"role2", "prop2":"someValue", "prop3":"whatever" },
{ "roleName":"role3", "prop2":"someValue", "prop3":"whatever" }
]
}
(Line breaks added for readability, but you'd remove them if creating a string.)
I don't know what your goal is but if you are using the HTML page as a GUI and Java for the processing you might as well use jsf or similar. There are multiple frameworks like primefaces, myfaces or icefaces that handle a lot of stuff for you.
Have a look at the Primefaces showcase if you're interested.
As MattBall suggested you can also use something like jaxb, this takes a lot of load off your hands.
You can use a lot of powerful and easy stuff.
You can map objects to JSON/XML using annotations:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Role
{
#XmlAttribute
private long id;
#XmlAttribute
private String name;
}
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class User
{
#XmlAttribute
private String userName;
#XmlAttribute
private String password;
#XmlElement
private ArrayList<Role> roles;
}
You can then use this in a web service:
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("user/{username}")
public User getUser( #PathParam("username") String userName)
{
User user;
// Get your user
return user;
}

Categories