I'm injecting a custom serializer using NEST.JsonNetSerializer like this
var settings = new ConnectionSettings(connPool, sourceSerializer: JsonNetSerializer.Default);
When I was using the built in serializer it camel cased the property names for me (from snake case) automatically. How can I make the custom serializer work the same way? I see that I can use ConnectionSettings.DefaultFieldNameInferrer() to specify how property names are inferred. But it seems unneccessary to copy the NEST code to make it work as before.
The only reason I'm not using the built-in serializer is because I have to work with dynamic models, and the internal JSON.NET objects in NEST are inaccessible.
Related
Jackson's #JacksonInject annotation is useful for declaring properties of your deserialized object that are to be "injected" by the code calling for deserialization (as opposed to only being parsed from the JSON). To use this feature, it seems you have to either:
Set the InjectableValues into the ObjectMapper (which would tie them to that ObjectMapper instance and be used for all calls to it).
Get an ObjectReader [via ObjectMapper.reader(InjectableValues)] and use that ObjectReader directly to parse the JSON.
Unfortunately, neither of these is doable (from what I can see) when using Spring's RestTemplate without jumping through a lot of hoops. I don't want every object being deserialized from the RestTemplate to use injected values; nor do I see a way to customize how RestTemplate uses the underlying ObjectMapper1.
Is there a way to incorporate InjectableValues into RestTemplate's JSON deserialization?
1I suppose I could write my own custom HttpMessageConverter and figure out how to inject that into RestTemplate. But even then I don't see a way to pass the InjectableValues into ObjectMapper's read... methods. It's a lot of work even if I could.
How can I globally configure json serializer for http4k? For example, snake case field names or formatting DateTime as ISO8601.
Since the ObjectMapper instance is private within ConfigurableJackson you cannot get at it after construction to do any configuration.
So you either need to construct your own direct instance of ConfigurableJackson and pass in a customized ObjectMapper or you need to subclass ConfigurableJackson with your own class. And then during the constructor, create an ObjectMapper (see example below) or intercept one being passed into your constructor and change its settings.
Whatever you do, be sure you do not break the http4k framework or anything else that might be using the same instance. You can see the defaults used by http4k declared in their source code:
object Jackson : ConfigurableJackson(ObjectMapper()
.registerModule(defaultKotlinModuleWithHttp4kSerialisers)
.disableDefaultTyping()
.configure(FAIL_ON_UNKNOWN_PROPERTIES, false)
.configure(FAIL_ON_IGNORED_PROPERTIES, false)
.configure(USE_BIG_DECIMAL_FOR_FLOATS, true)
.configure(USE_BIG_INTEGER_FOR_INTS, true)
)
You can use code similar to above to create your own instance.
See this thread for some conversation about this topic: https://github.com/http4k/http4k/issues/183
You don't necessarily need to extend ConfigurableJackson - it's just that extending it is the most convenient way to do this (in our experience).
All configuration is done by tweaking the ObjectMapper instance which is injected into the ConfigurableJackson constructor - the ConfigurableJackson itself just provides the wrapper API around that mapper. The question is to do with standard configuration of Jackson, so you should seek answers to your specific questions (snake case etc) from the Jackson docs directly as http4k doesn't own that API.
I have an API exposed via Spring Data Rest which, for the most part, is read-only but which allows for updating of some properties via PATCH requests.
Is there any (I'm supposing Jackson) configuration at a global level that would essentially make an entity read only unless specific properties were annotated in some way.
I am familiar with the#JsonProperty(access = Access.READ_ONLY) Jackson annotation however would like to avoid having to annotate all read-only properties.
For example, given the class below only the field explicitly annotated would be writable. All other fields would be readable by default:
public class Thing{
private String fieldOne;
#JsonProperty(access = Access.READ_WRITE)
private String fieldTwo;
private String fieldThree;
// a lot of other properties
}
Failing any global configuration, is there anything that can be applied at the class level?
I am not aware of any way to globally set all attributes in a class to read only. Since version 2.6+ of FaserXML you can use the following annotation to at least defined the set of properties you would ignore and only allow for serialization. The following annotation would be used at the class level:
#JsonIgnoreProperties(value={ "fieldOne", "fieldThree"}, allowGetters=true)
It is not exactly what you are looking for, but arguably makes coding a little easier.
I am currently using Guava's ForwardingMap as a base class and have numerous types that extend it. I need to maintain the Map type because instances need to be treated as such in consumers. So, even though internally the ForwardingMap using composition the external interface still has to be a map.
As a map, deserializing just key-value properties using #JsonAnyGetter and #JsonAnySetter work fine but, I also need to take into account custom properties, using #JsonProperty, which may also be a part of the instance as well.
So, when serializing or deserializing I want all of the entries and any custom properties which may be a part of the extended class.
I have looked at numerous types of solutions, such as using the Shape.OBJECT and apply interfaces, but none of them seem to work properly for me. I believe I need to create a custom deserializer/serializer to handle the bean + map processing in Jackson but cannot find any examples as to how to do this.
These links help to explain what I am trying to do with no luck:
http://www.cowtowncoder.com/blog/archives/2013/10/entry_482.html
How to serialize with Jackson a java.util.Map based class (cannot change base of ForwardingMap)
Jackson - ignore Map superclass when serializing (cannot change base because it needs to remain a Map)
Ideally, I would like an example or pointer of how to serialize and deserialize an instance that extends ForwardingMap using #JsonAnySetter and #JsonAnyGetter and has custom properties using #JsonProperty as well.
I would want my output to look like
"modules": {
"MyModel": { <-- extends ForwardingMap<>
"domain": "typeinfo",
"property":"hello", <-- comes from #JsonProperty
"another": "GoodBye", <-- comes from #JsonAnyGetter
"another2": 50 <-- comes from #JsonAnyGetter
}
}
I wrote a jackson module to enable a specific type of serialization. Now i want to enable global configuration of one of the new serializers. so i have to set a property on a serializer instance during creation.
Is there a way i can do that from within a jackson module?
Module interface is stateless, one-of-thing, so it does not have default wiring to affect things it adds.
But what you can do is to use a work-around; possibilities include:
use of ThreadLocal; set before serialization, read from serializer
use new (Jackson 2.3) feature of "attributes"; can set those for writing (ObjectWriter.setAttribute()) and reading (ObjectReader.setAttribute()), accessible by serializer/deserializer through context object (SerializerProvider / DeserializationContext)
So hopefully one of these works for your use case.