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

JsonSerializers are constructed multiple times when associated with SerializedName with alternate names but only one is used #2438

Closed
1 task
d-william opened this issue Jul 20, 2023 · 2 comments · Fixed by #2440
Labels

Comments

@d-william
Copy link
Contributor

d-william commented Jul 20, 2023

Gson version

2.10.1

Java / Android version

Java 17

Used tools

  • Maven; version: 3.8.1

Description

When a class has a field with :

  • @SerializedName annotation with alternate names
  • and with @JsonAdapter indicating a JsonSerializer class to use

Then a new JsonSerializer will instanciate for each alternate names, even if they will never be used (serialize is always false because of this)

Expected behavior

Instanciante a new JsonSerializer only for the main name, because created one can be an heavy operation.

Actual behavior

A new JsonSerializer will instanciate for each alternate names

Reproduction steps

Run the following code

public static class Pojo {

        @SerializedName(value = "field1", alternate = {"field2", "field3"})
        @JsonAdapter(StringSerializer.class)
        public final String str;

        public Pojo(String str) {
            this.str = str;
        }

}

public static class StringSerializer implements JsonSerializer<String> {

        private static int count = 0;

        private final int c;

        public StringSerializer() {
            this.c = count;
            System.out.println("new StringSerializer " + this.c);
            count++;
        }

        @Override
        public JsonElement serialize(String value, Type type, JsonSerializationContext context) {
            System.out.println("serialize " + this.c);
            return new JsonPrimitive(value);
        }

}

public static void main(String[] args) {
        TypeAdapter<Pojo> adapter = new Gson().getAdapter(Pojo.class);
        Pojo pojo1 = new Pojo("my value 1");
        Pojo pojo2 = new Pojo("my value 2");
        adapter.toJson(pojo1);
        adapter.toJson(pojo2);
}

Dev hint

Maybe we can give serialize value to this method call and used it in some way ?

OR

Create this type adapter before here

@Marcono1234
Copy link
Collaborator

Thanks for the report and for the hints on how this could be improved!

It looks like it is possible to even move the complete creation of the BoundField outside the loop, so you only have one BoundField per field (regardless of whether @SerializedName is used or not), see #2440.

@Marcono1234
Copy link
Collaborator

Instanciante a new JsonSerializer only for the main name, because created one can be an heavy operation.

As workaround you can specify a custom InstanceCreator which returns an existing instance of the serializer (respectively a singleton instance), for example:

Gson gson = new GsonBuilder()
   .registerTypeAdapter(MySerializer.class, (InstanceCreator<?>) t -> MySerializer.INSTANCE)
   .create();

It appears this is unfortunately not properly documented yet, see also #2442.

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

Successfully merging a pull request may close this issue.

2 participants