-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Custom static factory-based deserializer? #4004
Comments
Looks like this is especially important, because the default implementation will find a private constructor accepting a public Object createFromString(DeserializationContext ctxt, String value) throws IOException
{
if (_fromStringCreator != null) {
try {
return _fromStringCreator.call1(value);
} catch (Exception t) {
… A user may not realize that this internal constructor is being called, because it seemingly "just works". Unfortunately for my particular Because there is no easy way to register value types with I think such a facility definitely needs to be added and called out in the documentation. |
you can mark the factory method as a JsonCreator (with a mixin if necessary) |
Thanks, but the whole point of this exercise was to configure the mapper without modifying the class itself. |
then use a mixin? |
Why should I have to create a completely new class? Why can't there be an existing class I can simply instantiate, telling it the name of my factory method, or providing it with a method reference? I know there are workarounds. This ticket was opened so that I wouldn't have to use a workaround. |
if you dont want to add a mixin for some reason (e.g. because the name of the method is dynamic), you can instead add a value instantiator. |
I don't want to add a mixin because I don't want to write an extra class to go along with every value class I use, and I prefer not to litter the source code of the value class with serialization-specific annotations. I don't know why this request is difficult to understand. I can do this to serialize a class to a string: …
module.addSerializer(Bar.class, new ToStringSerializer());
… I want to do the analogous thing to register a deserializer for my value class, indicating the factory method to use. Do you agree that I'm even offering to write this class. I just want to make sure Tatu or someone will accept it so I don't waste my time doing it as part of the existing Jackson project. |
@garretwilson Tatu is on vacation. Can you wait a few weeks? |
Oh, sure, no problem at all! Believe me I have a thousand things ahead of this anyway on my list of things to do. For the moment I have this in my source code: //TODO create utility class; see https://github.com/FasterXML/jackson-databind/issues/4004
.addDeserializer(Bar.class, new JsonDeserializer<Bar>() {
@Override
public Bar deserialize(JsonParser parser, DeserializationContext context) throws IOException, JacksonException {
return Bar.of(parser.getValueAsString());
}
}) No rush on this—just wanted to file this while I was thinking about it. |
I believe you can declare a static method named either
|
Thanks, but the static factory method of my value class has a different name. And since you brought this up … 😁 I realize that at the time Jackson was written, However nowadays value classes/objects are better understood (see Fowler's ValueObject for an overview) and many newer languages include facilities for value classes built-in. The naming convention is evolving merely to use In essence Jackson, in recognizing P.S. I was just looking over the lesson I wrote on value objects around 10 years ago, and interestingly I find this sentence:
|
Sure, everybody has got their own preferences. Just letting you know such facility exists.
Now we know that thing you preferred doesn't exist in Jackson out-of-the-box. So whether the Jackson core maintainers want to accept it into the codebase or not, you'd still have to create it anyway to satisfy your personal preference, right? No reason to wait time to get cracking good luck. 👍 |
Ok I am back and... I think it makes sense to offer easier means for adding basic closure-based deserializer(s), maybe just (or at first) for things that accept JSON Strings, like more advanced ... that is, yes, exactly like you said. Implementation should probably also support We could perhaps extend |
Maybe we should make ValueInstantiator easier to implement (with a lambda?) and create a way to add it without a Module similar to (de)serializers. |
While |
As I noted on Stack Overflow, I'm using Java 17 and I have a
Bar
type I want serialized to JSON using itstoString()
method. I'm serializing using a JacksonObjectMapper
(created via aJsonMapper.Builder
). I found out from my other Stack Overflow question that I can specify aToStringSerializer
as a serializer in aModule
, as the answer indicated. (I had done this years ago, but forgotten how.)But now how about deserializing
Bar
using a static factory method? Looking at the code fromFromStringDeserializer.Std._deserialize(…)
, I see that known types are simply checked using acase
and then the static factory methods are explicitly invoked, e.g.Charset.forName(value)
orURI.create(value)
. This indicates to me that there may not be an existing deserializer for general serializer types—otherwise we could just usenew StaticFactoryDeserializer("forName")
andnew StaticFactoryDeserializer("create")
, etc. to do the same thing.Of course I can write one of these myself, but I'm curious whether this exists already. Basically I'd like to do this:
StaticFactoryDeserializer
would also allow aFunction
, so I could use it like this:(Probably the deserializer would create its own function instance internally when created with the method name, but that's an implementation detail.)
Does such a deserializer exist, or is one planned? If I wrote one, would it be something you'd be interested in including in Jackson?
The text was updated successfully, but these errors were encountered: