Skip to content

Automatically detect target type (Class) to deserialize to #5064

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

Open
rohanlopes20 opened this issue Apr 4, 2025 · 17 comments
Open

Automatically detect target type (Class) to deserialize to #5064

rohanlopes20 opened this issue Apr 4, 2025 · 17 comments
Labels
to-evaluate Issue that has been received but not yet evaluated

Comments

@rohanlopes20
Copy link

rohanlopes20 commented Apr 4, 2025

Is your feature request related to a problem? Please describe.

Currently to deserialize object in ObjectMapper we use below syntax -

ObjectMapper m = new ObjectMapper();
final String JSON = "{ \"x\" : 3 }";

Bean bean = m.readValue(JSON, Bean.class);

Can ObjectMapper automatically detect the class to be deserialized based on the return type?

This is already implemented in Mockito mockito/mockito#2779

Describe the solution you'd like

Below method can be added in ObjectMapper class to detect class automatically.

    public <T> T readValue(String content, T... reified) throws JsonProcessingException {
        if (reified.length > 0) {
            throw new IllegalArgumentException("Please don't pass any values here. Java will detect class automatically.");
        }
        return readValue(content, _typeFactory.constructType(getClassOf(reified)));
    }

Usage example

ObjectMapper m = new ObjectMapper();
final String JSON = "{ \"x\" : 3 }";

Bean bean = m.readValue(JSON);

Additional context

No response

@rohanlopes20 rohanlopes20 added the to-evaluate Issue that has been received but not yet evaluated label Apr 4, 2025
rohanlopes20 added a commit to rohanlopes20/jackson-databind-auto-detect-class that referenced this issue Apr 4, 2025
@rohanlopes20
Copy link
Author

https://github.com/rohanlopes20/jackson-databind-auto-detect-class

Created this fork for same.

@pjfanning
Copy link
Member

For me, this looks potentially useful.

Don't change yet but it might be better to target master branch instead of 2.19 branch. The master branch uses different package names (tools.jackson instead of com.fasterxml.jackson).

The tests need to be improved. Assert the values in the bean not just that it isn't null. More tests needed too.

@pjfanning
Copy link
Member

@cowtowncoder most of the code is copied from a Mockito PR. This has licensing implications. In the ASF, we would require that the LICENSE file is updated to include the MIT license from Mockito. Something along the licenses of saying that source file X has code copied from Mockito under the MIT License and then paste in the license.

@cowtowncoder
Copy link
Member

Hmmh. The last thing I want to import are license hassles. MIT is more permissive so it should be ok but... I guess as long as PR contains changes.

Also: same auto-detection should be, I think, added to ObjectReader.

@cowtowncoder
Copy link
Member

Forgot to mention: yes, if this works without adding complications for existing overloads, this seems like a very nice ergonomic improvement.

@JooHyukKim
Copy link
Member

JooHyukKim commented Apr 4, 2025

Good one! Like we have in Kotlin extension.
Just some related article about this reified Generics in case anyone curious.

@JooHyukKim
Copy link
Member

FYI, we have several readValue methods that we can apply this solution.

@JooHyukKim
Copy link
Member

@rohanlopes20 Just wondering, are you planning on contributing? :))) Seems like you almost have it.

@rohanlopes20
Copy link
Author

rohanlopes20 commented Apr 6, 2025

Yes, I am checking reader code based on above comment. I saw some methods which can use this but seems like there are no test cases for same.

Also, can you let me know what else is required in tests other than checking not null objects? @cowtowncoder @JooHyukKim

rohanlopes20 added a commit to rohanlopes20/jackson-databind-auto-detect-class that referenced this issue Apr 6, 2025
@rohanlopes20
Copy link
Author

@cowtowncoder Saw ObjectReader code, not sure if my understanding is correct but below 1st method is public.

    public <T> T readValue(InputStream src) throws IOException
    {
        if (_dataFormatReaders != null) {
            return (T) _detectBindAndClose(_dataFormatReaders.findFormat(src), false);
        }
        return (T) _bindAndClose(_considerFilter(createParser(src), false));
    }

    public <T> T readValue(InputStream src, Class<T> valueType) throws IOException
    {
        return (T) forType(valueType).readValue(src);
    }

If below code added to handle autodetection then it directly refers to code block above(1st method ObjectReader#readValue(InputStream src) instead of reified code. In this case we have to make it private. Pretty sure that is incorrect(testSerializeAsExternalizable this test fails too).

    public <T> T readValue(InputStream src, T... reified) throws IOException
    {
        return forType(getClassOf(reified)).readValue(src);
    }

Can you please guide what needs to be done ? Don't want to break jackson standards. You can commit in fork if required. https://github.com/rohanlopes20/jackson-databind-auto-detect-class

@cowtowncoder @JooHyukKim

@JooHyukKim
Copy link
Member

Can you please guide what needs to be done ? Don't want to break jackson standards. You can commit in fork if required. https://github.com/rohanlopes20/jackson-databind-auto-detect-class

If we do this for Jackson 3, we could just remove the existing public <T> T readValue(InputStream src) method?
That's only if our new reified (InputStream src, T... reified) method wouldn't break any performance/implementation.

@rohanlopes20
Copy link
Author

I did that but it broke test case testSerializeAsExternalizable.

@JooHyukKim
Copy link
Member

And where is the failing test result? Let's write a PR so we can all see what's going on

rohanlopes20 added a commit to rohanlopes20/jackson-databind-auto-detect-class that referenced this issue Apr 6, 2025
@rohanlopes20
Copy link
Author

#5071

org.opentest4j.AssertionFailedError:
Expected :com.fasterxml.jackson.databind.interop.TestExternalizable$MyPojo@56a6d5a6
Actual :com.fasterxml.jackson.databind.interop.TestExternalizable$MyPojo@55740540

@JooHyukKim

@cowtowncoder
Copy link
Member

Ahhh. I forgot the basic thing about ObjectReader -- right we do not actually want to do similar overloads: the idea is that ObjectReader is constructed with/for target type, so readValue() methods do not take target type.
There was later addition of readValue() with target type, for 2.x: I now wish I had not accepted that PR.
These are removed from 3.0.

So I think type detection wrt ObjectReader should only be done, possibly, for constructing ObjectReader instances -- but not 100% that is doable. That is, only for ObjectMapper methods of form:

public ObjectReader readerFor(JavaType type)

then something like

public <T> ObjectReader readerFor(T... reified)

if that is possible -- and importantly, if that is actually usable from caller perspective.

Does this make more sense?

@rohanlopes20
Copy link
Author

If that is the case then will revert changes for other readValue methods.

For above case below works -

public <T> ObjectReader readerFor(T... reified) {
        // Detect class type
        Class<T> clazz = getClassOf(reified);

        // Convert class to JavaType
        JavaType valueType = _config.getTypeFactory().constructType(clazz);

        return forType(valueType);
    }

Test Case

   @Test
    public void testAutoDetectForReader() throws Exception
    {
        Number n = MAPPER.reader().readerFor().readValue("123 ");
        assertEquals(Integer.valueOf(123), n);
    }

@rohanlopes20
Copy link
Author

@cowtowncoder @JooHyukKim Can you check and revert please.

@cowtowncoder cowtowncoder changed the title Automatically detect class to deserialize Automatically detect target type (Class) to deserialize to Apr 10, 2025
rohanlopes20 added a commit to rohanlopes20/jackson-databind-auto-detect-class that referenced this issue Apr 12, 2025
rohanlopes20 added a commit to rohanlopes20/jackson-databind-auto-detect-class that referenced this issue Apr 12, 2025
rohanlopes20 added a commit to rohanlopes20/jackson-databind-auto-detect-class that referenced this issue Apr 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
to-evaluate Issue that has been received but not yet evaluated
Projects
None yet
Development

No branches or pull requests

4 participants