public class ConnectedEntry {
private EntryInScores scores;
private EntryInValues values;
private String someString;
public ConnectedEntry(EntryInScores scores, EntryInValues values) {
this.scores = scores;
this.values = values;
this.someString = "Adasd";
}
I have an object that looks more or less like this, and I use it as a GET response for my API. scores and values are both database entities. I wanted to add a String to the response with some additional information.
What happens is that the objects are properly turned into a JSON and they show up in the response, but the string is omitted, with no error: it's just not there.
I tried wrapping the string in a wrapper class, but it didn't help.
What could I do?
Usually Spring uses Jackson as the default converter from objects to JSON. In order for Jackson to convert to JSON you must provide getters, so that Jackson can get and convert those values. As I can see in your representation you don't have any getters. Try providing getters for the fields that you wish to convert. Never make fields public!
You can go for creating json object and put the data as key value pair to resolve this issue.
Happy Coding!!!
Related
I have a large nested object. I want to serialise this object in the JSON string, however I need only certain fields to be included. Problem here is that fields could change very frequently and I want to build it in a way that could help me easy include or exclude fields for serialisation.
I know that I can write a lot of code to extract certain fields and build JSON "manually". But I wonder if there are any other elegant way to achieve similar outcome but specifying a list of required fields?
For example having following object structure I want include only id and name in the response:
class Building {
private List<Flat> flats;
}
class Flat {
private Integer id;
private Person owner;
}
class Person {
private String name;
private String surname;
}
Json:
{
"flats" : [
{
"flat":
{
"id" : "1",
"person" : {
"name" : "John"
}
}
}
]
}
You can use gson for serializing/deserializing JSON.
Then you can include the #Expose annotation to use only the fields you require.
Be sure to also configure your Gson object to only serialize "exposed" fields.
Gson gson = GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Alternative:
You can actually do it the inverse way, marking fields which will not be exposed. You can do this with the transient keyword.
So whatever you want to ignore just add transient to it. Here's how it works on gson.
PS: This works on most Java JSON serializers too.
Using com.fasterxml.jackson.annotation.JsonIgnore is another way to achieve this.
import com.fasterxml.jackson.annotation.JsonIgnore;
class Person {
private String name;
#JsonIgnore
private String surname;
}
It will ignore the surname when the parser converts the bean to json.
Similar annotation will be available in other json processing libraries.
If using Gson, study how to use ExclusionStrategy & JsonSerializer.
Using those is a more flexible way to control serialization since it allows to decide per serialization what to serialize.
Using annotations requires later to add / remove those annotations from fields if there is a need to change what to serialize.
In the case of your example the latter might be more appropriate.
This question might be good startpoint
serialize-java-object-with-gson
I used RestTemplate to call some 3rd-Party APIs, and RestTemplate will convert received JSON to java POJO automatically like this:
Result result = restTemplate.getForObject(url, Result.class);
But sometimes the JSON structure is quite simple, such as the two examples:
{"access_token":"abcdefg","expires_in":7200} //only need access_token
{"status":0,"result":{"x":25,"y":46}} //only need "x" and "y"
Should I create POJOs for every JSON response in different structure?
For example, the POJO for the first JSON structure:
public class TokenResult {
private String access_token;
private String expires_in;
/* Getters and Setters */
......
}
For the second JSON structure:
public class CoordResult {
private String status;
private Coordinate result;
/* Getters and Setters */
......
}
public class Coordinate {
private String x;
private String y;
/* Getters and Setters */
......
}
I don't think it is elegant to do so, because some JSON structures are very simple and some are used only once like the "access_token" response.
Any ideas on how to avoid too many simple POJOs?
The example you have there are perfectly fine. Even if it feels you have too many POJOs with property members that are not used this IMO is best and future proof approach. Imagine in near future you need to implement functionality that will require access to TokenResult.getExpiresIn() this would mean you would still end up refactoring the base POJO and adding that method and class member.
In similar example with the CoordResult I see the status as a quite important property that would need checking once the response is received so mapping that to a class member in a POJOs is very good idea.
This will make your code more resilient and also predictive with well defined structure and encapsulating all available data from the response.
Though if you have similar responses in terms of context and structure you can always extend a base POJO and add the relevant class members to a child class.
Another benefit is that this all makes the client code easy to read as we can tell what we expect from the response objects and that can be used in different implementations many of which may not applicable and visible now.
If you decide you don't need all properties of a JSON response you can still use #JsonIgnoreProperties annotation on the class and it'll exclude any unknown elements from the JSON mapping.
EX:
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
#JsonIgnoreProperties(ignoreUnknown = true)
public class TokenResult {
private String access_token;
// you don't need this
// private String expires_in;
}
If you're looking for just some values from the response you could try the org.json package ( http://www.json.org/javadoc/ ). It has methods to access values in a JSON response.
String jsonStr = "{\"access_token\":\"abcdefg\",\"expires_in\":7200}";
String accessToken = new JSONObject(jsonStr).getString("access_token");
This approach gets a little more tricky trying to nested values.
I am using Spring and Java and implementing REST Based services. I have a set of developers who develop for mobile,iPad and Web too. Consider I have a bean
Class User{
private String Name;
private Integer id;
private String photoURL;
private ArrayList<String> ProjectName;
private ArrayList<String> TechnologyList;
private ArrayList<String> InterestList;
//Getters and setters
}
While the Web Developers need the entire fields and mobile developers just require two fields from it whereas the iPad requires something in between mobile and web.
Since I am using jackson as a parser, is there a way where while requesting to the controller I can specify which all data I require and avoid the others. For example consider I do a GET request like
GET>http://somedomain.com/users?filter=name,id,photoUrl
Which returns me a JSON structure something like
{
"name":"My Name",
"id":32434,
"photoUrl":"/sss/photo.jpg"
}
Sameway if someone asks for some more fields, they could be filtered. Please let me know how this can be done so that my API remains generic and useable for all.
You can achieve what you want but some extra work is necessary. I can offer you two solutions.
1. Return a Map
Simply put every property that is requested into the map.
2. Use Jacksons Object Mapper directly
Jackson lets you set filters that specify which properties are serialized or ignored.
FilterProvider filter = new SimpleFilterProvider().addFilter("myFilter",
SimpleBeanPropertyFilter.filterOutAllExcept(requestedProperties));
String json = objectMapper.writer(filter).writeValueAsString(value);
You can then return the JSON string directly instead of an object.
For both solutions you would ideally write a class that does the job. But if you do that you could as well write your own message converter. You could extend the MappingJackson2HttpMessageConverter, for instance, and overwrite the writeInternal method to suit your needs. That has the big advantage that you don't need to change your controllers.
The straightforward solution is to implement custom Jackson JSON serializer that will get field names that should be serialized from thread local storage and then serialize only fields which names are presented in that context. For other hand, in controller you can grab all allowed fields names from url and store them into thread local context. Hope this helps.
Say I have the following class:
public class Parent {
public int age;
#JsonUnwrapped
public Name name;
}
Producing JSON:
{
"age" : 18,
"first" : "Joey",
"last" : "Sixpack"
}
How do I deserialize this back into the Parent class? I could use #JsonCreator
#JsonCreator
public Parent(Map<String,String> jsonMap) {
age = jsonMap.get("age");
name = new Name(jsonMap.get("first"), jsonMap.get("last"));
}
But this also effectively adds #JsonIgnoreProperties(ignoreUnknown=true) to the Parent class, as all properties map to here. So if you wanted unknown JSON fields to throw an exception, you'd have to do that yourself. In addition, if the map values could be something other than Strings, you'd have to do some manual type checking and conversion. Is there a way for Jackson to handle this case automatically?
Edit:
I might be crazy, but this actually appears to work despite never being explicitly mentioned in the documentation: http://fasterxml.github.io/jackson-annotations/javadoc/2.2.0/com/fasterxml/jackson/annotation/JsonUnwrapped.html
I was pretty sure it didn't work for me previously. Still, the proposed #JsonCreator approach might be preferred when custom logic is required to deserialize unwrapped polymorphic types.
You can use #JsonCreator with #JsonProperty for each field:
#JsonCreator
public Parent(#JsonProperty("age") Integer age, #JsonProperty("firstName") String firstName,
#JsonProperty("lastName") String lastName) {
this.age = age;
this.name = new Name(firstName, lastName);
}
Jackson does type checking and unknown field checking for you in this case.
It does work for deserialization as well, although it's not mentioned in the docs explicitly, like you said. See the unit test for deserialization of #JsonUnwrapped here for confirmation - https://github.com/FasterXML/jackson-databind/blob/d2c083a6220f2875c97c29f4823d9818972511dc/src/test/java/com/fasterxml/jackson/databind/struct/TestUnwrapped.java#L138
#JsonUnwrapped works for both serialization and deserialization, you shouldn't need to take any additional steps.
Despite not being mentioned in the Javadocs prior to Jackson 2.13 (per
jackson-annotations#184), the #JsonUnwrapped annotation does apply to deserialization as well as serialization, so no additional work is needed to support deserialization of a field using the annotation.
The Jackson 2.13 Javadocs for #JsonUnwrapped clarify that the annotation applies to deserialization as well as serialization:
Annotation used to indicate that a property should be serialized "unwrapped" -- that is, if it would be serialized as JSON Object, its properties are instead included as properties of its containing Object -- and deserialized reproducing "missing" structure.
[...]
When values are deserialized "wrapping" is applied so that serialized output can be read back in.
For those who googled here like me, trying to resolve issue when deserializing unwrapepd Map, there is a solution with #JsonAnySetter:
public class CountryList
{
Map<String, Country> countries = new HashMap<>();
#JsonAnySetter
public void setCountry(String key, Country value)
{
countries.put(key, value);
}
}
For example, at the moment I am getting a list of restaurants from a Google API. then I have to create a a restaurant class with getters and setters, then I have to create objects of that class and populate them with each field from the returned json manually.
Is there another way to do this quicker than manually doing all the work?
The best thing is to find libraries for that particular API. Failing that, you could consume the JSON without mapping them to Java Beans (i.e. just parse the JSON and work with the parsed JSON by doing parsed.getString("city_name") etc.). Jackson is a good library to do that.
You could also try generating a JSON schema out of the returned JSON, then using that to auto generate Java Beans code, and then use this with a JSON library like Jackson. I tried this once but it seems that you have to fix the generated JSON schema quite a bit as the automatic schema generation tools referenced above isn't very good at the moment.
What I do is just create an object that matches the returned json string and place the values into the object using gson.fromjson()
Object.
public class Return {
private String Status;
private String[] Data;
public Return(String Status, String[] Data){
this.Status=Status;
this.Data=Data;
}
public String getStatus() { return Status; }
public String[] getData() { return Data; }
}
Code to populate Object.
java.lang.reflect.Type listType = new TypeToken<Return>(){}.getType();
Return return2= new Gson().fromJson(myresponse.toString(), listType);