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

Kryo5 deserialization lost Locale script field #1053

Open
hanbing204 opened this issue Mar 5, 2024 · 1 comment
Open

Kryo5 deserialization lost Locale script field #1053

hanbing204 opened this issue Mar 5, 2024 · 1 comment
Labels

Comments

@hanbing204
Copy link

Describe the bug
java.util.Locale script field in the is missing after deserialization with Kryo5, when we execute below UT method. we expect to get sr_RS_#Cyrl but actually we get the sr_RS which script is lost

expected [sr_RS_#Cyrl] but found [sr_RS]
java.lang.AssertionError: expected [sr_RS_#Cyrl] but found [sr_RS]

To Reproduce

  @Test
  public void testLocaleScript() {
    Kryo kryo = new Kryo();
    kryo.setRegistrationRequired(false);

    Locale locale = new Locale.Builder().setLanguage("sr").setScript("Cyrl").setRegion("RS").build();

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try (Output output = new Output(baos)) {
      kryo.writeClassAndObject(output, locale);
    }
    
    Object deserializedLocale;
    try (Input input = new Input(baos.toByteArray())){
      deserializedLocale = kryo.readClassAndObject(input);
    }

    assertEquals(deserializedLocale.toString(), "sr_RS_#Cyrl");
  }

Environment:

  • OS: Windows/OSX/Ubuntu
  • JDK Version: JDK17
  • Kryo Version: 5.5.0
@theigl
Copy link
Collaborator

theigl commented Mar 6, 2024

It is quite trivial to add support for script to LocaleSerializer, but I'm afraid it is not possible to do it in a backwards-compatible way.

For now, you can register your own script-aware serializer for locales:

public static class ScriptAwareLocaleSerializer extends ImmutableSerializer<Locale> {

    public void write (Kryo kryo, Output output, Locale l) {
        output.writeAscii(l.getLanguage());
        output.writeAscii(l.getCountry());
        output.writeString(l.getVariant());
        output.writeAscii(l.getScript());
    }

    public Locale read (Kryo kryo, Input input, Class<? extends Locale> type) {
        String language = input.readString();
        String country = input.readString();
        String variant = input.readString();
        String script = input.readString();
        return create(language, country, varian, script);
    }

    protected Locale create (String language, String country, String variant) {
        if (script != null) {
            return new Locale.Builder()
                    .setLanguage(language)
                    .setRegion(country)
                    .setVariant(variant)
                    .setScript(script)
                    .build();
        } else {
            return new Locale(language, country, variant);
        }
    }
}
kryo.addDefaultSerializer(Locale.class, ScriptAwareLocaleSerializer.class);

It might make sense to make this the default in Kryo 6.

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

No branches or pull requests

2 participants