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

Unresolved forward reference from seemingly valid json #235

Closed
masoncj opened this issue Jun 3, 2013 · 14 comments
Closed

Unresolved forward reference from seemingly valid json #235

masoncj opened this issue Jun 3, 2013 · 14 comments

Comments

@masoncj
Copy link

masoncj commented Jun 3, 2013

Using the attached JSON file, Jackson 2.2.2, and the following code, I see the error:

Exception in thread "main" java.lang.IllegalStateException: Could not resolve Object Id [544068%2FTaxonomicItem] (for [simple type, class rnrm.RNRMDot$ReferenceThingTemplate]) -- unresolved forward-reference?
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectId(BeanDeserializerBase.java:962)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1041)
object RNRMDot {

    def main(args: Array[String]) {
        val mapper = new ObjectMapper() with ScalaObjectMapper
        mapper.registerModule(DefaultScalaModule)
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

        val roots = mapper.readValue[Array[ReferenceThingTemplate]](new FileInputStream(args(0)))

        System.out.println(roots(0).uri)
    }

    @JsonIdentityInfo(generator = classOf[ObjectIdGenerators.PropertyGenerator], property = "uri")
    case class ReferenceThingTemplate(
                                      uri:String,
                                      children:Array[ReferenceThingTemplate],
                                      edgeKinds:Array[String],
                                      hasChildren:Boolean,
                                      displayLabel:String,
                                      comment:String,
                                      id:Int
                                      ) { }
}

544068 is a top level object that is later referenced in an array in a child (I've also attached a screenshot that makes this easier to see). The id field appears early in the data, just after the _type field) and before any children objects. This seems like it should be valid, and we have client side code that parses it using a map. This seems simliar to issue 97 but the presence of the id field early in the data seems to distinguish it.

@masoncj
Copy link
Author

masoncj commented Jun 3, 2013

screen shot 2013-06-03 at 1 14 43 pm

@masoncj
Copy link
Author

masoncj commented Jun 3, 2013

@cowtowncoder
Copy link
Member

I am guessing that the problem may be that properties are fed via constructor parameters -- and this prevents binding of id of the container, before deserializing its contents.
If so, this may be a fundamental limitation; but on plus side, can be solved if (case) class is refactored to take children as non-ctor-parameter properties (field or setter are fine). Assuming you can use case classes this way (I don't know Scala limitations well enough to know).

@cowwoc
Copy link

cowwoc commented Nov 28, 2014

@cowtowncoder I think I just ran into this limitation.

I've got:

{
  "@id" : 1,
  "current" : {
    "@id" : 2,
    "parent" : 1,
    "uri" : "http://www.google.com/",
    "current" : null,
    "hasNext" : true
  },
  "hasNext" : false,
  "parent" : null
}

and Jackson fails to deserialize with: com.fasterxml.jackson.databind.deser.UnresolvedForwardReference: Could not resolve Object Id [1] (for [simple type, class com.realestate.task.GoToNextCompany]). at [Source: realestate.xml; line: 5, column: 17]

Where line 5, column 17 refers to "parent" : 1. And yes, you're right that class Child has a constructor that takes class Parent as an argument.

I want to require this as a constructor argument to ensure the Object is well-formed. Moving the logic into a setter would potentially allow bad objects to get constructed.

  1. Does any other workaround that comes to mind?
  2. Can you improve the error message to point to a Wiki page with an explanation and a list of possible workarounds?
  3. If I had to choose, I'd require Child to take Parent in the constructor, but allow setting Parent.child using a setter (since in my case, children are populated lazily during the object's lifetime)... but based on what I can see Jackson doesn't give me that option. I am forced to decouple the parent link, not the children. Is that correct?

@pgelinas
Copy link
Member

You should try using 2.4.X: resolution of forward reference was revamped and I think it is now supported.

@cowwoc
Copy link

cowwoc commented Nov 28, 2014

@pgelinas I am seeing this problem on 2.4.3.

@cowwoc
Copy link

cowwoc commented Nov 28, 2014

Odd. In theory this should be fixed by 2.4.4 using #610. I upgraded to 2.4.4 but I still get the error. Any ideas?

@pgelinas
Copy link
Member

Ok, OP from 2013 indicated 2.2.2; I had to be sure about version used ;)

In this case, it might be related to constructor params, I'd have to check. Constructor params have a special kind of treatment, so it might be that forward reference isn't properly handled for creator properties. I quickly skimmed the code and I think there is indeed something missing. Unfortunately, I'm not in an environment where I can test and debug this right now.

@cowwoc
Copy link

cowwoc commented Nov 28, 2014

@pgelinas Something is funky, to be sure. I am not able to reproduce the problem in a minimal testcase (meaning, forward references work there) so I am slowly adding more and more detail from my real application to see when it breaks.

@cowwoc
Copy link

cowwoc commented Nov 28, 2014

@pgelinas Ah ha! Got it. This bug only occurs if the constructor contains: @JacksonInject Foo foo. If you don't use any @JacksonInject arguments then forward references work fine. I am in the process of filing a separate bug report for this case.

@cowwoc
Copy link

cowwoc commented Nov 28, 2014

@pgelinas filed #639. Attaching testcase in a minute.

@cowtowncoder
Copy link
Member

I am guessing it probably invokes different code path; deserializer has a few distinct paths, some involving more optimized handling, others for buffering, and this can result in incomplete handling for some features.

@cowwoc
Copy link

cowwoc commented Dec 19, 2014

Filed a second bug related to resolved forward-references: #658

@cowtowncoder
Copy link
Member

I think the new bugs cover the new problem, and it's better to close this one since it has bit different history (i.e. there are multiple underlying problems).

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

4 participants