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

Bug in polymorphic deserialization with @JsonCreator, @JsonAnySetter, JsonTypeInfo.As.EXTERNAL_PROPERTY #3045

Closed
martineaus83 opened this issue Feb 5, 2021 · 3 comments
Milestone

Comments

@martineaus83
Copy link

martineaus83 commented Feb 5, 2021

I'm using Jackson for a while in simply way. I've just tried some more difficult tricks and I found a strange behaviour.

When I've combined JsonCreator annotation with a JsonTypeInfo.As.EXTERNAL_PROPERTY resolver, then the result is not the same than if I had not put the @JsonCreator.

My example is simple : I want to deserialize this String :

{ "time":345,
  "type":"track",
  "data":{"data-internal":"toto"}
}

My classes are


	public static class MyData {
		@JsonAnySetter
		public HashMap data = new HashMap();
		@Override
		public String toString() {
			StringBuilder buf = new StringBuilder();
			buf.append("[");
			Set<Entry> entrySet = data.entrySet();
			for (Entry e : entrySet) {
				buf.append("[").append(e.getKey()).append("=").append(e.getValue()).append("]");
			}
			buf.append("]");
			return buf.toString();
		}
	}

	public static class MyJson {
		private long time;
		private String type;
		private Object data;

		public MyJson() {
		}
		public long getTime() {
			return time;
		}
		public void setTime(long time) {
			this.time = time;
		}
		public String getType() {
			return type;
		}
		public void setType(String type) {
			this.type = type;
		}
		public Object getData() {
			return data;
		}
		@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
		@JsonTypeIdResolver(ChildBaseByParentTypeResolver.class)
		public void setData(Object data) {
			this.data = data;
		}
	}

	public static class MyJson2 {
		private final long time;
		private String type;
		private Object data;

		@JsonCreator
		public MyJson2(@JsonProperty("time") long t) {
			System.out.println("MyJson2<init>");
			time = t;
		}
		public long getTime() {
			return time;
		}
		public String getType() {
			return type;
		}
		public void setType(String type) {
			this.type = type;
		}
		public Object getData() {
			return data;
		}
		@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
		@JsonTypeIdResolver(ChildBaseByParentTypeResolver.class)
		public void setData(Object data) {
			this.data = data;
		}
	}

When I launch the the two deserialization, I have the next results

content = {"time":345,"type":"track","data":{"data-internal":"toto"}}
MyJson result
time=345
type=track
data=class com.navalgroup.sdms.ac.model.impl.test.TestDeserialisation$MyData ; [[data-internal=toto]]

MyJson2 result
time=345
type=null
data=null

When I've got the sources and I've tried to debug the unexpected MyJson2 result, I've lost myself in BeanDeserializer.deserializeUsingPropertyBasedWithExternalTypeId. The Json datas seem to be put in TokenBuffer which doesn't seem used.

I attached a fully executed Java File with my test classes.
TestDeserialisation.zip

Thanks for your attention

@martineaus83 martineaus83 added the to-evaluate Issue that has been received but not yet evaluated label Feb 5, 2021
@martineaus83
Copy link
Author

My Jackson version, for the test, is 2.12.0

@cowtowncoder cowtowncoder added 2.13 and removed to-evaluate Issue that has been received but not yet evaluated labels Feb 17, 2021
@cowtowncoder
Copy link
Member

Not sure what the problem might be, thank you for providing the reproduction code. I hope to have a look in near future but this may take a while.

The difference between @JsonCreator is likely buffering: without use of creator buffering is typically not needed (since instance can be created immediately and properties can be handled in any order), whereas with creator buffering is usually needed (to hold all arguments before calling constructor, if multiple arguments; or if type id does not come first in JSON). That in itself should not cause loss of contents so this definitely looks like a bug; but I just mention this as it is likely related.

@cowtowncoder cowtowncoder added 2.12 and removed 2.13 labels Feb 17, 2021
@cowtowncoder cowtowncoder changed the title Bug in deserialization Bug in polymorphic deserialization with @JsonAnySetter, JsonTypeInfo.As.EXTERNAL_PROPERTY Feb 17, 2021
@cowtowncoder cowtowncoder changed the title Bug in polymorphic deserialization with @JsonAnySetter, JsonTypeInfo.As.EXTERNAL_PROPERTY Bug in polymorphic deserialization with @JsonCreator, JsonTypeInfo.As.EXTERNAL_PROPERTY Feb 20, 2021
@cowtowncoder cowtowncoder changed the title Bug in polymorphic deserialization with @JsonCreator, JsonTypeInfo.As.EXTERNAL_PROPERTY Bug in polymorphic deserialization with @JsonCreator, @JsonAnySetter, JsonTypeInfo.As.EXTERNAL_PROPERTY Feb 20, 2021
@cowtowncoder
Copy link
Member

Found one problem, fixed, but looks like there are multiple flawed code paths.

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

2 participants