kryo
kryo copied to clipboard
Kryo5 deserialization lost Locale script field
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
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.