Skip to content

Gson.toJson incorrectly serializes collection of objects with some circumstances (see unit test) #754

@pkravtsov

Description

@pkravtsov

I guess it is something wrong with TypeAdapter cache mechanism for collections.

My Java version:

java version "1.7.0_80"
Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)

Gson dependency:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.5</version>
</dependency>

Just run this unit test:

package pkravtsov;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

import com.google.gson.Gson;

public class GsonTest {
    class R {
          List<B> blist;
        }

        class B {
          int b = 1;
          List<R> rlist;
        }

        class C extends B {
          int c = 2;
        }

        class A {
          List<B> a;
        }

    @Test
    public void testToJsonObject() {
        Gson gson = new Gson();
        List<Object> source = new ArrayList<Object>();
        A a = new A();
        a.a = new ArrayList<B>();
        a.a.add(new B());
        a.a.add(new C());
        source.add(a);
        String expected = "[{\"a\":[{\"b\":1},{\"c\":2,\"b\":1}]}]";
        String result = gson.toJson(source);
        assertEquals(expected, result);


        gson = new Gson();// This line is essential to reproduce the bug! Do not use previous successful gson instance!
        source = new ArrayList<Object>();
        source.add(new B());
        a = new A();
        a.a = new ArrayList<B>();
        a.a.add(new B());
        a.a.add(new C());
        source.add(a);
        expected = "[{\"b\":1},{\"a\":[{\"b\":1},{\"c\":2,\"b\":1}]}]";
        String wrong = "[{\"b\":1},{\"a\":[{\"b\":1},{\"b\":1}]}]";
        result = gson.toJson(source);
        assertEquals(wrong, result);
        assertEquals(expected, result);
    }

}

This unit test will be successful if you do any of the following:

  1. Move line "source.add(new B());" after "source.add(a);" (do not forget to update "expected" value appropriately).
  2. Remove R.blist (do not forget to update "expected" value appropriately).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions