Ignore field with annotation for JSON serialization but not for Mongo in MongoJack - mongo-jackson-mapper

Is there any possibility to ignore field for JSON serialization (for web display) but not for mongo (internal serialization) ?
I`ve tried so far all these methods but field was also ignored for Mongo, or not ignored in both in case of some variations
Jackson: how to prevent field serialization

Ok, I finally solved this.
objectMapper.writerWithView(Views.Public.class).writeValueAsString(lo));
writeValueUsingView is from another version of Jackson, so it wasn't working

Custom serialization for web/mongo can be solved by using #JsonView annotations, try along these lines:
class Views {
static class OnAllViews {}
static class OnlySomeViews extends OnAllViews {}
...
}
public class Thing {
#JsonView(Views.OnAllViews.class) Integer id;
#JsonView(Views.OnlySomeViews.class) String name;
}
and then you can call the appropriate level of serialization through writeValueUsingView method.
objectMapper.writeValueUsingView(out, beanInstance, ViewsPublic.class);
You can read more about it here.

Related

How to include a nested PropertyBusinessObject in a PropertyBusinessObject json?

My app contains several PropertyBusinessObject entities, and most of them have nested PropertyBusinessObject objects as properties.
For instance, a Note has a parent User which had written the note, so the Note entity contain a Property<User, Note> which is instantiated with the User.class and the name of the property.
Here is the code of the Note Entity:
public class Note extends AbstractEntity
{
public final Property<User, Note> author = new Property<>("author", User.class);
public final Property<String, TarotNote> text = new Property<>("text");
public Note() {}
}
AbstractEntity implements the PropertyBusiness interface and define the methods to be overridden by the entities to properly implements the interface.
And here is the result JSON from PropertyIndex.toJson:
{
"author": "our.app.backend.entity.User#77203809",
"text": "test"
}
Do I need to override the toString method of all my entities to be sure to not have this behavior (seems to be the wrong way...) ? Or (I hope) is there another way?
For your information, the parsing of the Json issued from the server works perfectly fine with nested entities.
This seems like a logic bug in the JSON generation code, I've added code to fix this here: https://github.com/codenameone/CodenameOne/commit/34447f62971d8bb696116f02c97bac9b70de89b6

How can I prevent Spring Data Rest from from nulling out #CreatedDate during updates?

I am trying spring-data-rest with spring-data-mongo and a lot of things are working beautifully out of the box, including support for eTag field.
#EnableMongoAuditing annotations works very well too: when a document is created, the #CreatedDate and #LastModifiedDate fields are set.
The problem is that the #CreatedDate field being set to null during updates. I found an unresolved issue Mongo Auditing: #CreatedDate field gets set to null on updates with Spring Data Rest with a suggested workaround of using the #JsonIgnore annotation which does not work for me.
There was also a similar question here which does not appear to be the same issue.
I am using version 1.10.1.RELEASE of spring-data-mongo and 2.6.1.Release of spring-data-rest.
Is there a solution to this issue?
One solution is to tell Jackson to output the field to JSON when serializing the object, but never read the value when deserializing the object, using the access element of JsonProperty:
#Document
public class MyDocument {
#JsonProperty(access = JsonProperty.Access.READ_ONLY)
#CreatedDate
private Instant createdDate;
}
Spring Data REST will still output the createdDate field to JSON, but it will never read from it, including when performing an update.
Note that this will affect the serialization of your document class throughout the entire application. Often this will not be an issue, but it would pose a problem if there are other places in the code that need to be able to deserialize the createdDate from JSON.
Created date make sense only for immutable entities (which you are not going to update)
If entity is updatable, would like to use only last modified instead
For any other cases probably make sense use some history audition log..
#Entity
// ...
public class MyEntity {
// ...
#CreatedDate
private LocalDateTime createdAt; // modifiedAt
#PreUpdate
public void fixSpringDataRestNullDate() {
createdAt = LocalDateTime.now();
}
}

ApiTransformer for parametrized, unavailable type

I'm using Objectify and wish to have its Key<> type passed around in my API. I've created an ApiTransformer, but my questions is where to declare it, since the serialized Key<> class is not available, hence I cannot declare its transformer as a class annotation. I tried declaring it in the #Api annotation, but it doesn't work, I still get the error:
There was a problem generating the API metadata for your Cloud Endpoints classes: java.lang.IllegalArgumentException: Parameterized type com.googlecode.objectify.Key<[my package].User> not supported.
The ApiTransformer looks like:
public class KeyTransformer implements Transformer<Key<?>, String> {
public String transformTo(Key<?> in) {
return in.getString();
}
public Key<?> transformFrom(String in) {
return Key.valueOf(in);
}
}
And in my #Api I have:
#Api(name = "users", version = "v1",transformers = {KeyTransformer.class})
Unfortunately you can't. As you said you need to declare it on the Key class, your only chances to make this work are either.
1) Recompile the Key class for objectify with the #transformer annotation.
2) Extend the Key class with your own implementation and define the transformer there.
I don't really like any of those options so the way i usually resolve this is to hide the key object getter (by using #ApiResourceProperty(ignored=AnnotationBoolean.TRUE)) and only expose the id from that key.
That way you get a Endpoints frendly object, the only downside is you'll have to reconstitute the key using Key.create(YourClass.class, longId) manually whenever you need it.
You can add transforms to 3rd party classes by listing the transform in #Api annotation. I'm not dead sure it'll work parameterized class, but I don't see why not.
https://cloud.google.com/appengine/docs/java/endpoints/javadoc/com/google/api/server/spi/config/Api#transformers()

solr: read stopword.txt in Custom Handler

I want to read stopword.txt in my custom handler. How to do that ? I know that this is used in Filtering and can be done from there. But I need to read that list in my Custom UpdateRequestProcessorFactory. Also can I read any other custom file created by me.
I was aware that limitation. I overlooked that you are using about update processor.
I looked into the code, here is an existing code you can use as example. SolrCoreAware is the interface you are after.
public class StatelessScriptUpdateProcessorFactory extends UpdateRequestProcessorFactory implements SolrCoreAware
#Override
public void inform(SolrCore core) {
resourceLoader = core.getResourceLoader();
}
Classes that implement org.apache.lucene.analysis.util.ResourceLoaderAware can read files under conf directory. However what it your use case anyway?
looks like xy problem

Error deserializing read-only property with Jackson

In My CXF-based REST layer I am using Jackson for seializing/deserializing Groovy objects. The issue I am experiencing deals with deserializing a property that does not have a setter method. There is a domain object Dashboard with getGroups() method returning a list of Group objects. Upon serialization this object is properly converted to JSON with "group" attribute. When I send the object for update from JavaScript, JSON still has the "group" attribute. Since the property is read-only on the domain object I would like to simply ignore the "group" property when deserializing JSON.
Since I am using Jackson mix-ins, I tried various combination of #JsonIgnore, #JsonGetter and #JsonProperty annotations - all to no avail. If the property is available upon serialization, I get the error below in deserialization. I can clean the JSON object in JavaScript by removing the "group" attribute, bit I would like to find a server-side solution.
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Problem deserializing 'setterless' property 'groups': get method returned null (through reference chain: org.ozoneplatform.commons.server.domain.model.DashboardTemplate["groups"])
at com.fasterxml.jackson.databind.deser.impl.SetterlessProperty.deserializeAndSet(SetterlessProperty.java:114)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:198)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:577)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObjectUsingNonDefault(BeanDeserializer.java:393)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:289)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
at com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:1169)
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:625)
at com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider.readFrom(JacksonJsonProvider.java:448)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBody(JAXRSUtils.java:1038)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameter(JAXRSUtils.java:614)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameters(JAXRSUtils.java:578)
at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:238)
How can I tell Jackson to ignore a read-only property on deserialization?
Thank you,
Michael
After many fruitless hours, I have finally found the magic combination of spells that addresses such a seemingly trivial issue. In the mixin I had to create this combination of annotations:
#JsonIgnore
abstract Set<Group> groups
#JsonProperty
abstract Set<Group> getGroups()
#JsonIgnore
abstract void setGroups(Set<Group> groups)
On top of that I had to add two configuration parameters to the ObjectMapper:
mapper.configure(MapperFeature.USE_GETTERS_AS_SETTERS, false)
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
Isn't there a simpler way to achieve the same?
Michael
I had the same issue. Solution was to give the getter the correct name:
List list...
setList(...)
was correct, but my getter was
setProductList() which produced the "setterLess" error. changing it to:
setList(...) resolved the issue
I just ran into the same problem, and my solution was to create a private, no-op setter:
public class MyFoo {
public String getMyStr() {
return "hello, world";
}
private void setMyStr(String ignored) {}
}
Making setMyStr private prevents me from accidentally trying to call it from my code, but Jackson still finds it and invokes it. Little does jackson know -- or care -- that invoking it does nothing.

Resources