question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Data structure that cannot be serialized properly

See original GitHub issue

Below is the data structure and serialization method I defined.

@Getter
@Setter
public class Base {
	private String baseField;
	private Base child;
}

@Getter
@Setter
public class Child1 extends Base {
	private List<Integer> child1Field;
}

@Getter
@Setter
public class Child2 extends Base {
	private List<Integer> child2Field;
}

public class Test {
	public static void main(String[] args) throws JsonProcessingException {
		Base base = new Base();
		base.setBaseField("base");

		Base child1 = new Child1();
		child1.setBaseField("child1");
		List<Integer> child1Field = Lists.asList(1, new Integer[]{1});
		((Child1)child1).setChild1Field(child1Field);

		Base child2 = new Child2();
		child2.setBaseField("child2");
		List<Integer> child2Field = Lists.asList(2, new Integer[]{2});
		((Child2)child2).setChild2Field(child2Field);

		child1.setChild(child2);
		base.setChild(child1);

		System.out.println(new Gson().toJson(base));
	}
}

I thought that the result I got was like this:

{
    "baseField": "base", 
    "child": {
        "baseField": "child1", 
        "child": {
            "baseField": "child2", 
            "child2Field": [
                2, 
                2
            ]
        }, 
        "child1Field": [
            1, 
            1
        ]
    }
}

But the result I got is like this:

{
    "baseField": "base", 
    "child": {
        "baseField": "child1", 
        "child": {
            "baseField": "child2"
        }
    }
}

I lost the value of childXField. What is going on here? Is it a data type that does not support such recursive references?

Issue Analytics

  • State:open
  • Created 4 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
lyubomyr-shaydarivcommented, Oct 24, 2019

Not a bug, this is how Gson was designed. The reason of such design, I guess, is that you cannot restore the original Base object unless you have enough information to deserialize the object from the JSON document. You can make it work in write-only way like this:

gsonBuilder.registerTypeAdapterFactory(new TypeAdapterFactory() {
	@Override
	public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
		final Class<? super T> rawType = typeToken.getRawType();
		if ( !Base.class.isAssignableFrom(rawType) ) {
			return null;
		}
		@SuppressWarnings("unchecked")
		final TypeAdapter<T> delegateTypeAdapter = (TypeAdapter<T>) gson.getDelegateAdapter(this, TypeToken.get(rawType));
		return new TypeAdapter<T>() {
			@Override
			public void write(final JsonWriter out, final T value)
					throws IOException {
				delegateTypeAdapter.write(out, value);
			}

			@Override
			public T read(final JsonReader in) {
				throw new UnsupportedOperationException();
			}
		};
	}
})

This type adapter would write expected JSON payload. However, your DTO classes structure makes me think RuntimeTypeAdapterFactory would fit your needs.

0reactions
Marcono1234commented, Dec 13, 2021

The underlying issue for this specific case seems to be #1833. Gson should produce the JSON data you are expecting, but due to that bug it erroneously prefers the reflective type adapter for the base type (Base) instead of the reflective type adapter for the subtype (Child1).


Note that I am not a member of this project.

Read more comments on GitHub >

github_iconTop Results From Across the Web

The redux best practice "Do Not Put Non-Serializable Values ...
This article explains one of the four react-redux best practices: "Do Not Put Non-Serializable Values in State or Actions"
Read more >
NotSerializableException in Java with Examples
In Java, a NotSerializableException exception is thrown when an instance of a class must implement the Serializable interface. The exception is ...
Read more >
Serializing Python Objects - Dive Into Python 3
On the surface, the concept of serialization is simple. You have a data structure in memory that you want to save, reuse, or...
Read more >
c# - protobuf-net: Cannot serialize type data, How can I define ...
There's a couple of issues in this approach; yes, in standard protocol buffers any kind of Type metadata is a bit naughty, ...
Read more >
Serializing Data Structures in C [closed]
C has no native support for serializing structures, so you're on your own. The first order approximation is (as stated in other replies)...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found