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!!!
I have the following class.
// Adding Lombok's #Data / #Value gives an error
public class Sample {
String id;
String name;
Dummy[] entries;
#JsonCreator
// #Builder --> This gives same error
private Sample(
#JsonProperty("id") final String id,
#JsonProperty("name") final String name,
#JsonProperty("entries") #NonNull final Dummy[] entries) {
this.id = id;
this.name = name;
this.entries = entries;
}
}
If I add Lomobok annotations, I get the following error. We heavily rely on Lombok and I am trying to figure out how I can ensure I don't return a mutable object.
EI_EXPOSE_REP: May expose internal representation by returning reference to mutable object
EI_EXPOSE_REP2: May expose internal representation by incorporating reference to mutable object
As an alternative, I could use List instead of Array and rely on #Singular annotation. But I would like to know if there is a workaround for Array with Lombok's annoations.
One way to solve this is to add some lombok config. The way to do this is in the root of the project (the same place your pom.xml/build.gradle is) add a file called:
lombok.config.
In this file add the following lines:
config.stopBubbling = true
lombok.addLombokGeneratedAnnotation = true
lombok.extern.findbugs.addSuppressFBWarnings = true
lombok.anyConstructor.addConstructorProperties = true
More info here:
https://projectlombok.org/features/configuration
It's an old and well known problem with methods generated by Lombok that return or accept mutable objects or structures.
For example this issue about Date was submitted in 2015.
It is unlikely that Lombok will ever fix this because it's non-trivial.
Your options :
Disable particular FindBugs/SpotBugs inspection via build tool plugin or IDE configuration.
Place #SuppressFBWarnings with relevant error code on violating class.
Use onX Lombok feature to let it place #SuppressFBWarnings on violating methods(setters,getters etc.) like in snippet below.
#Data
#Setter(onMethod_ = #SuppressFBWarnings({"EI_EXPOSE_REP2","EI_EXPOSE_REP"}))
#Getter(onMethod_ = #SuppressFBWarnings({"EI_EXPOSE_REP2","EI_EXPOSE_REP"}))
public class TheClass {
private MutableClassOrStructure classOrStructure;
}
If I have a class using Lombok:
#RequiredArgsConstructor
#Getter
class Example {
private final String id;
}
And try to deserialize it from
{
“id”: “test”
}
Jackson throws an exception that although at least one creator was provided, it could not deserialize.
If I then add another final String field to that class, and add that field to the JSON, it is deserialized with no complaints.
Does anyone know what’s going on here? Why are you unable to deserialize if you only have one field?
When only way to intialize object properties is through contructor, Jackson needs to be told that deserialization should happen using constructor via #JsonCreator annotation.
Also, all the property names should be provided via #JsonProperty annotation because Jackson needs to know the sequence of attributes passed in contructor to correctly map json values to Java object attributes.
So, if you are not using lombok contructor, then constructor will look like
#JsonCreator
public Example (#JsonProperty("id") String id) {
this.id = id;
}
If you don't want to manually write the contructor, go ahead with #tashkhisi's answer.
Also, I highly doubt following could happen. Could you update the question with code showing this?
If I then add another final String field to that class, and add that field to the JSON, it is deserialized with no complaints.
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
How can Jackson be configured to ignore a field value during serialization if that field's value is null.
For example:
public class SomeClass {
// what jackson annotation causes jackson to skip over this value if it is null but will
// serialize it otherwise
private String someValue;
}
To suppress serializing properties with null values using Jackson >2.0, you can configure the ObjectMapper directly, or make use of the #JsonInclude annotation:
mapper.setSerializationInclusion(Include.NON_NULL);
or:
#JsonInclude(Include.NON_NULL)
class Foo
{
String bar;
}
Alternatively, you could use #JsonInclude in a getter so that the attribute would be shown if the value is not null.
A more complete example is available in my answer to How to prevent null values inside a Map and null fields inside a bean from getting serialized through Jackson.
Just to expand on the other answers - if you need to control the omission of null values on a per-field basis, annotate the field in question (or alternatively annotate the field's 'getter').
example - here only fieldOne will be omitted from the JSON if it is null. fieldTwo will always be included in the JSON regardless of if it is null.
public class Foo {
#JsonInclude(JsonInclude.Include.NON_NULL)
private String fieldOne;
private String fieldTwo;
}
To omit all null values in the class as a default, annotate the class. Per-field/getter annotations can still be used to override this default if necessary.
example - here fieldOne and fieldTwo will be omitted from the JSON if they are null, respectively, because this is the default set by the class annotation. fieldThree however will override the default and will always be included, because of the annotation on the field.
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Foo {
private String fieldOne;
private String fieldTwo;
#JsonInclude(JsonInclude.Include.ALWAYS)
private String fieldThree;
}
UPDATE
The above is for Jackson 2. For earlier versions of Jackson you need to use:
#JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
instead of
#JsonInclude(JsonInclude.Include.NON_NULL)
If this update is useful, please upvote ZiglioUK's answer below, it pointed out the newer Jackson 2 annotation long before I updated my answer to use it!
With Jackson > 1.9.11 and < 2.x use #JsonSerialize annotation to do that:
#JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
In Jackson 2.x, use:
#JsonInclude(JsonInclude.Include.NON_NULL)
You can use the following mapper configuration:
mapper.getSerializationConfig().setSerializationInclusion(Inclusion.NON_NULL);
Since 2.5 you can user:
mapper.setSerializationInclusion(Include.NON_NULL);
You can set application.properties:
spring.jackson.default-property-inclusion=non_null
or application.yaml:
spring:
jackson:
default-property-inclusion: non_null
http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
in my case
#JsonInclude(Include.NON_EMPTY)
made it work.
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonInclude(JsonInclude.Include.NON_EMPTY)
should work.
Include.NON_EMPTY indicates that property is serialized if its value is not null and not empty.
Include.NON_NULL indicates that property is serialized if its value is not null.
This Will work in Spring boot 2.0.3+ and Jackson 2.0+
import com.fasterxml.jackson.annotation.JsonInclude;
#JsonInclude(JsonInclude.Include.NON_NULL)
public class ApiDTO
{
// your class variable and
// methods
}
If you want to add this rule to all models in Jackson 2.6+ use:
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
If in Spring Boot, you can customize the jackson ObjectMapper directly through property files.
Example application.yml:
spring:
jackson:
default-property-inclusion: non_null # only include props if non-null
Possible values are:
always|non_null|non_absent|non_default|non_empty
More: https://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html#howto-customize-the-jackson-objectmapper
For Jackson 2.5 use :
#JsonInclude(content=Include.NON_NULL)
If you're trying to serialize a list of object and one of them is null you'll end up including the null item in the JSON even with
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
will result in:
[{myObject},null]
to get this:
[{myObject}]
one can do something like:
mapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
#Override
public void serialize(Object obj, JsonGenerator jsonGen, SerializerProvider unused)
throws IOException
{
//IGNORES NULL VALUES!
}
});
TIP: If you're using DropWizard you can retrieve the ObjectMapper being used by Jersey using environment.getObjectMapper()
This has been troubling me for quite some time and I finally found the issue. The issue was due to a wrong import. Earlier I had been using
com.fasterxml.jackson.databind.annotation.JsonSerialize
Which had been deprecated. Just replace the import by
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;
and use it as
#JsonSerialize(include=Inclusion.NON_NULL)
Global configuration if you use Spring
#Configuration
public class JsonConfigurations {
#Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.serializationInclusion(JsonInclude.Include.NON_NULL);
builder.serializationInclusion(JsonInclude.Include.NON_EMPTY);
builder.failOnUnknownProperties(false);
return builder;
}
}
We have lot of answers to this question. This answer may be helpful in some scenarios
If you want to ignore the null values you can use the NOT_NULL in class level.
as below
#JsonInclude(Include.NON_NULL)
class Foo
{
String bar;
}
Some times you may need to ignore the empty values such as you may have initialized the arrayList but there is no elements in that list.In that time using NOT_EMPTY annotation to ignore those empty value fields
#JsonInclude(Include.NON_EMPTY)
class Foo
{
String bar;
}
Case one
#JsonInclude(JsonInclude.Include.NON_NULL)
private String someString;
Case two
#JsonInclude(JsonInclude.Include.NON_EMPTY)
private String someString;
If someString is null, it will be ignored on both of cases.
If someString is "" it just only be ignored on case two.
The same for List = null or List.size() = 0
Try this -
#JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
public class XYZ {
protected String field1;
protected String field2;
}
And for non-null values (On getters/class level) -
#JsonSerialize(include=JsonSerialize.Inclusion.NON_EMPTY)
Jackson 2.x+ use
mapper.getSerializationConfig().withSerializationInclusion(JsonInclude.Include.NON_NULL);
Also, you have to change your approach when using Map myVariable as described in the documentation to eleminate nulls:
From documentation:
com.fasterxml.jackson.annotation.JsonInclude
#JacksonAnnotation
#Target(value={ANNOTATION_TYPE, FIELD, METHOD, PARAMETER, TYPE})
#Retention(value=RUNTIME)
Annotation used to indicate when value of the annotated property (when used for a field, method or constructor parameter), or all properties of the annotated class, is to be serialized. Without annotation property values are always included, but by using this annotation one can specify simple exclusion rules to reduce amount of properties to write out.
*Note that the main inclusion criteria (one annotated with value) is checked on Java object level, for the annotated type, and NOT on JSON output -- so even with Include.NON_NULL it is possible that JSON null values are output, if object reference in question is not `null`. An example is java.util.concurrent.atomic.AtomicReference instance constructed to reference null value: such a value would be serialized as JSON null, and not filtered out.
To base inclusion on value of contained value(s), you will typically also need to specify content() annotation; for example, specifying only value as Include.NON_EMPTY for a {link java.util.Map} would exclude Maps with no values, but would include Maps with `null` values. To exclude Map with only `null` value, you would use both annotations like so:
public class Bean {
#JsonInclude(value=Include.NON_EMPTY, content=Include.NON_NULL)
public Map<String,String> entries;
}
Similarly you could Maps that only contain "empty" elements, or "non-default" values (see Include.NON_EMPTY and Include.NON_DEFAULT for more details).
In addition to `Map`s, `content` concept is also supported for referential types (like java.util.concurrent.atomic.AtomicReference). Note that `content` is NOT currently (as of Jackson 2.9) supported for arrays or java.util.Collections, but supported may be added in future versions.
Since:
2.0