Spring MVC force Jackson to only use setters - java

I have a Spring MVC application which uses Jackson and the #RequestBody annotation.
I have a field in the POJO that I do not want Jackson to map, so I have lombok set the setter access level to NONE.
#NotNull
#Setter(AccessLevel.NONE)
private boolean enabled = false;
I have tried to force Spring's ObjectMapper bean to only use setters by configuring as:
#Bean
#Primary
public ObjectMapper getObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.NONE);
return mapper;
}
I would assume that with no setter and no visability of the field Jackson would not map up the "enabled" field... but if I send a body with enabled set to true it maps it,
Can anyone advise what else I need to do?
Thanks

Just annotate the field with #JsonProperty and set access to read only.
#JsonProperty(access = Access.READ_ONLY)
private boolean enabled;
PS. You don't need to annotate with #NotNull or initialise to false since you're using a primitive type.

Related

Java serialization using objectMapper: serialize using private getter

I have a private field with a private getter method (because I hope to prevent other users from using the getter outside this class, while I have a use case for this getter within this class), but I hope the field to be serialized using objectMapper. What is a good way to do it? Would appreciate any idea!
#Data
public class TestClass{
#Getter(AccessLevel.PRIVATE)
private String field
}
ObjectMapper by default will serialize only public fields, but you can change it using setVisibility method.
You can do it like this:
TestClass testClass = new TestClass("field");
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
objectMapper.writeValueAsString(testClass);

Use custom object in Jackson constructor

Is there a way to provide the Jackson Deserializer with a default value from "the outside" (e.g. DI container) that it will use when deserializing an object, in this case tagRegistry?
#JsonCreator
public ExtractionRule(#JsonProperty("id") String id,
TagRegistry tagRegistry) {
this.id = id;
this.tagRegistry = tagRegistry;
}
I couldn't find an easy way to do this.
You could try #JacksonInject. Add this member to the ExtractionRule class:
#JacksonInject("tagRegistry")
private TagRegistry tagRegistry;
And inject the tagRegistry to the ObjectMapper before deserialization:
InjectableValues.Std injectableValues = new InjectableValues.Std();
injectableValues.addValue("tagRegistry", tagRegistry);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setInjectableValues(injectableValues);
I haven't tried using it in a constructor, not sure if that works.
You can find further examples here:
https://www.logicbig.com/tutorials/misc/jackson/jackson-inject.html
https://www.concretepage.com/jackson-api/jackson-jacksoninject-example#JacksonInject

Serialize #JsonIgnore-d field

I have class with #JsonIgnore-d field:
public class MyClass {
...
#JsonIgnore
private SomeType myfield;
...
// getters & setters
}
Is it possible to configure ObjectWriter so that it includes myfield during serialization even though being ingored?
Rationale: MyClass is serialized in many places and only in single specific one I want to have myfield.
It is possible to configure ObjectMapper to disable a JsonIgnore function. Following are some possible solution you can try with:
1.
Disable JsonIgnore function for a particular annotated field.
You can create a custom JsonIgnore annotation and a custom JacksonAnnotationIntrospector to remove the annotation from mapper context.
Following are the ideas:
Annotate #MyJsonIgnore to the fields that should be ignored while serialization:
#JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class MyClass {
#MyJsonIgnore
private SomeType myField;
}
#MyJsonIgnore is a simple custom annotation that wrap #JsonIgnore:
#Retention(RetentionPolicy.RUNTIME)
#JacksonAnnotationsInside
#JsonIgnore
public #interface MyJsonIgnore {
}
A custom JacksonAnnotationIntrospector is implemented to remove #MyJsonIgnore from mapper context:
public class DisablingMyJsonIgnoreIntrospector extends JacksonAnnotationIntrospector {
#Override
public boolean isAnnotationBundle(final Annotation ann) {
if (ann.annotationType().equals(MyJsonIgnore.class)) {
return false;
} else {
return super.isAnnotationBundle(ann);
}
}
After that, you can set the introspector on a ObjectMapper during configuration:
ObjectMapper mapper = new ObjectMapper();
mapper.setAnnotationIntrospector(new DisablingMyJsonIgnoreIntrospector());
It results that the fields annotated with #MyJsonIgnore can be marshaled properly.
2.
Disable JsonIgnore function for the mapper
Your can create a custom JacksonAnnotationIntrospector and override hasIgnoreMarker method to always return false:
public static class DisablingJsonIgnoreIntrospector extends JacksonAnnotationIntrospector {
#Override
public boolean hasIgnoreMarker(final AnnotatedMember m) {
return false;
}
}
hasIgnoreMarker is to check whether there is annotation to ignore json property. Return false will disable the JsonIngore function.
3.
Disable all annotations and specify what kinds of properties are auto-detected for a given ObjectMapper:
final ObjectMapper mapper = new ObjectMapper();
mapper.disable(MapperFeature.USE_ANNOTATIONS);
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
This simply disable all annotations.
Hope this can help.
One more option is to use the AnnotationIntrospector.nopInstance() if you want to avoid all Jackson's annotations in your pojo including #JsonIgnore e.g.
JsonMapper.builder().annotationIntrospector(AnnotationIntrospector.nopInstance()).build()...
or
new ObjectMapper().setAnnotationIntrospector(AnnotationIntrospector.nopInstance())...

Hibernate and Jackson lazy serialization

I'm working on a project using Hibernate and Jackson to serialize my objects.
I think I understand how it is suposed to work but I can't manage to make it works.
If I understand well, as soon as a relation fetch mode is set to LAZY, if you want this relation, you have to initialize it.
Here is my class :
#Entity
#JsonIgnoreProperties(ignoreUnknown = true)
#Table(schema="MDDI_ADMIN", name = "MINIUSINE")
#Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public class MiniUsine {
#Id
#Column(name="MINIUSINEID", nullable = false)
private int miniUsineID;
#Column(name = "NAME", length = 40, nullable = false)
private String name;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name="FluxID")
#JsonInclude(JsonInclude.Include.NON_EMPTY)
private Set<Flux> fluxs = new HashSet<Flux>();
And all getters and setters.
I've also tried this JsonInclude.Include.NON_EMPTY as class annotation. Also tried the NON_NULL.
However, jackson keeps sending me
com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: MiniUsine.fluxs, no session or session was closed (through reference chain: java.util.ArrayList[0]->MiniUsine["fluxs"])
I'm serializing it with : mapper.writeValueAsString(optMU);
Using Jackson 2.3.2
Thanks for help
I know this is an old question but I had the same problem.
You must add a new maven dependecy to support JSON serialization and deserialization of Hibernate. I used Hibernate5 so I added
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate5</artifactId>
<version>2.9.2</version>
</dependency>
Now register the new module.
#Provider
public class JacksonHibernateProvider implements ContextResolver<ObjectMapper> {
#Override
public ObjectMapper getContext(final Class<?> type) {
final ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Hibernate5Module());
return mapper;
}
}
As far as I understand, the entity object that hibernate returns is a proxy which derives from your entity class. If you try to access getter methods for lazy fields outside of a transaction, you get LazyInitializationException.
The point I want to make is setting fluxs to empty set doesn't help you at all.
private Set<Flux> fluxs = new HashSet<Flux>();
Hibernate overloads the getter and if you try to access it outside of a transaction(which jackson is doing to check if it is empty), you get the LazyInit error.

Getting JsonIgnore or JsonIgnoreProperties to work on servlet filter

The Java object has to be serialized into a json string in the servlet filter for a jersey application.
Have the following object,
#XmlRootElement
#JsonIgnoreProperties({"bar"})
public class Foo{
String a="1";
String b="2";
#JsonIgnore
String bar="3";
};
ObjectMapper om = new ObjectMapper();
om.writeValueAsString(fooObject);
returns,
{
a:"1",
b:"2",
bar:"3" // Inspite of Jsonignore and jsonignoreproperties bar is returned
}
How do I overcome this?
Fixing the imports to fasterxml from codehaus and adding the following feature to the mapper fixed the issue.
mapper.configure(MapperFeature.USE_ANNOTATIONS, true);
use #XmlTransient:
#XmlTransient
String bar="3";

Categories

Resources