Best practice to create POJO / DTO for sending deep nested JSON - java

When developing our API in spring boot that interacts with a third party API, I have to create a DTO to populate and send to a third party. Thing is, the required JSON has a ton of nested objects. For example:
{
"profile": {
"firstName": "firstname",
"credentials": {
"password" : {
"hook": {
"type": "default"
}
}
}
}
}
So, what is simple to express in a JSON object is not simple to express in POJO/DTO classes, due to the high number of nested objects.
Should I create public or anonymous classes for all the nested properties? Or is there a better way to do this?
For example using anonymous, I can keep everything in one java file by not making the subobjects public. What are your techniques for this?

known problem... what I used often:
wrap (hide) third party api in a module
create custom pojo(s) containing only values needed from your domain logic
use only this pojo(s) to interact between your domain/third party module
create module private/inner classes mapping the third party api model as pojos
or consider using nested maps instead with custom jackson de/serializers
map domain pojo to api pojos
or, a bit hacky, if you only need to change same values
store json request payload as a template with placeholders
use e.g. regex to replace before send

You can do what you suggested or simply de-serialize it into Map<String, Object> Using map makes it easy but you won't have content validation and modifying the content (if you need it becomes complex)

Related

How to get object JSON with no get/set methods

Most of the json serializations work using object property accessors like getter and setter methods. I am trying to serialize third party object with no get/set methods(and I don't have control to modify source) to json and send over REST service.
But the final json produced doesn't have all the properties data as like in my object. This is obvious due to no accessor methods.
Is there any other way I can prepare JSON in this scenario?
Otherwise, is there any other way I can send this 3rd party object over my rest service as is without compromising on it's properties values? (I considered like object serialization and send using streams, but that looks like unconventional).
Maybe most. GSON on the other hand uses reflection to directly setup fields. You actually have to force it to not use reflection (see Gson avoid reflection).
So one solution would be to use that library. And just to be precise: gson uses reflection to identify the fields in your bean classes directly, without relying on getters/setters.

How to return JSON in HTTP client library?

I want to create a library which will do the authentication stuff (sending some authentication parameters along the request) and return the json response from an API. The JSON will usually represent an array of dictionaries, something like this:
[
{"a": 1, "b": 2},
{"a": 3, "b": 1}
]
I have done the same thing in Python and there it was no-brainer, I just return a dict which is builtin in Python.
I was wondering what would be the best way in Java? Here are some of the approaches I consider:
Returning a stream which will be handled by user. Specifically, I use java.net.HttpURLConnection and by this approach I will return connection.getInputStream() which will be handled by the user. The drawback of this approach is that the user would need to do great part of the job (reading the stream and converting it to json-like object or whatever). The good part is the users will have flexibility to process it in any way they like, creating custom objects from classes, using third party json libraries or something else. By this approach I don't force them to use some library, because the whole code will use Java builtin functionalities.
Use third party library, like org.json or GSON and return that kind of object. The drawback here is that I'll force the user to use third party library.
I could define classes for each kind of objects, there would be probably 5-6 type of classes. The drawbacks are: I will need more time to implement the solution and will force the user to use my objects.
What bothers me is that Python developers very often use dict, while in Java the developers most often prefer to work with objects of specific user defined classes. So, I can't conclude what would be the most appropriate way.
Any endpoint for an HTTP API has a defined response structure (or at least it should). The methods implemented by your library should return a POJO that represents the response payload. The end user should not need to be aware that the API formats the payload in JSON. If the API one day decides to use XML, that change should be transparent to the users of your library.
Edit: simply returning a dictionary, or map type is bad practice. Doing so forces users of your library to assume the key strings and value type of each property in the response. A POJO provides a clear definition of the response property names and their value types.

is there a way to configure paritally or fully serializion to json using jersey?

I want to serialize a java object using jersey.
I want to serialize it and print it to file.
It's a big object and i want to save it twice:
one in a short version with mandatory fields only.
second in full version with all fields.
Is there a way to do so, other than create two DTOs
and duplicate the small object from the big object and then serialize them both to json?
To make it fast, Jersey help making REST webservices and Jackson help to manage a JSON Object.
So you can use both and have more ways to play with your objects.
Extending the JsonSerializer you could provide 2 custom serializer with the behaviour you want. I don't repost the link i put in comment, but there's an example in it.
Just to be sure, for me a non flat object is an object with private attributes that are business object to. If it is, yes, you could serialize a non flat object.
To serialize non flat objects, in my opinion there are two ways. And i based my development on the link i provided in comments (Item, User, Main class...).
First one, the composed one are simple so i could use something like this :
jgen.writeStartObject();
jgen.writeNumberField("id", value.id);
jgen.writeStringField("itemName", value.itemName);
jgen.writeObjectFieldStart("owner");
jgen.writeNumberField("id", value.owner.id);
jgen.writeStringField("name", value.owner.name);
jgen.writeEndObject();
jgen.writeEndObject();
In this case, the owner is composed with two fields, pretty simple.
The second solution is to use one another serializer :
One for main object, one for the composite and use :
jgen.writeObjectField("owner.", value.owner);
and don't forget to add the composed object serializer with :
module.addSerializer(User.class, new UserSerializer());
hope this help

java/jersey/jackson - validate input JSON

I am writing a REST API with a Java/Jersey/Jackson stack. All JSON parsing and generating is done with Jackson. The REST layer is handled by Jersey. It will be embedded in a Grizzly container.
In my API, I accept JSON in my endpoints. For example:
#POST
public Response post(final SomeObject input) {
return ...;
}
What is the best way to validate the input? There are certain things I would like to validate:
input must be not null
certain fields of input must be not null
certain fields of input must follow a regular expression (text fields)
certain fields of input must be in a range (numeric fields)
...
If possible, I would like to change my code as less as possible. That is, I prefer to annotate my classes, methods and parameters to integrate the validation.
You can use a JSON Schema.
And since you use Jackson, you can use my library which does exactly that.
However this means you'd need to change your logic so that you receive the JSON (as a JsonNode) instead of the serialized POJO, and only then serialize to your POJO.
You can also BeanValidationApi (javax.validation.constraints) and then annotate your fields with #NotNull,#Pattern, etc. Jersey also provides Bean Validation Support

Extra/dupe members in SOAP response prevents serialization (Axis, Java, Gson)

I am using Axis to call a SOAP-based web service. I'm then trying to serialize the returned remote object as JSON, using the Google Gson library.
The serialization to JSON fails, with Gson complaining that "there are multiple elements with the name __equalsCalc()).
When I inspect the returned object in my IDE (Eclipse), I can see that this is true -- the returned object has three members called __equalsCalc() and another three called __hashCode.
I know from looking around that these are added by WSDL2Java (I think) in order to avoid recursion. My question is, why are there THREE of each? And how can I get the serializer to ignore these? They're not actually part of the object's definition (it's called a RemoteProject, for reference). Can I do something hackish like cast the RemoteProject to a RemoteProject to get it to drop those members?
This turns out to be not too hard to solve. I have multiple copies of the same instance var because the class being serialized is shadowing fields of the same name from superclasses. Since I don't care about these fields, the best approach in Gson is to write a custom ExckusionStrategy which can selectively ignore fields based on their name:
http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/ExclusionStrategy.html
I don't know GSon.
With Jackson, you can annotate properties (i.e - fields that have getters/setters according to Java bean convention) with #JsonIgnore.
This way you can prevent issues like recursion/no matching setter or getter and so on...
Try to find out if you have the same at GSon or use Jackson.

Categories