Skip to content
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

ObjectMapper convertValue does not check if the value is already of target type #4661

Closed
lorenzbaier opened this issue Aug 13, 2024 · 6 comments

Comments

@lorenzbaier
Copy link

Why does objectMapper.convertValue not check if the object already has the desired target type and then return the object immediatly.

// inlined 'writeValue' with minor changes:

When converting a class which has a recursive getter of some form, I expect to get the object back immediatly if it has the correct type to begin with.

@Test
  void testConvertRecursive() {
    var convertedTp = new ObjectMapper().convertValue(new Recursive(), Recursive.class);
    assertNotNull(convertedTp);
  }

  public record Recursive(String name) {
    Recursive() {
      this("test");
    }

    public Recursive getSelf() {
      return new Recursive();
    }
  }

Instead I get: Infinite recursion (StackOverflowError) (through reference chain:....

@cowtowncoder
Copy link
Member

Have a look at method definition (

* Note that behavior changed slightly between Jackson 2.9 and 2.10 so that
); there's some notes on why short-cut is not taken -- this used to be the behavior, but it is problematic for true conversion case where behavior between "proper" conversion (serialize-then-deserialize) and "fake" one (omit doing anything if type is already expected).

Issue for change in 2.10 was this:

#2220

@lorenzbaier
Copy link
Author

Oh sry I didn't see that but thanks for pointing that out.

However I am wondering what is really meant by "let caller handle optimizations if ones are desired" (from #2220)?
How would you intercept the conversion of certain objects?

@yawkat
Copy link
Member

yawkat commented Aug 14, 2024

Instead of mapper.convertValue(x, T.class), callers can just do if (!(x instanceof T)) mapper.convertValue(x, T.class).

@lorenzbaier
Copy link
Author

sure the "first" level is not a problem, but what if the object is deeper down in the hierarchy?

@yawkat
Copy link
Member

yawkat commented Aug 14, 2024

I don't think it's feasible at a deeper level. convertValue works by serializing and then deserializing. During serialization, the serializer has no knowledge of what type a particular property will eventually be deserialized to. So I don't see a generic approach happening.

If you have some contextual information you could eg create a serializer that uses writeEmbeddedObject instead of actually serializing a particular type.

@lorenzbaier
Copy link
Author

Okay thanks for the info, I will look into a more specific solution that fits my use case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants