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

Nested Object Serialization #21

Closed
Silthus opened this issue Dec 2, 2021 · 1 comment
Closed

Nested Object Serialization #21

Silthus opened this issue Dec 2, 2021 · 1 comment
Labels
good first issue Good for newcomers invalid This doesn't seem right

Comments

@Silthus
Copy link

Silthus commented Dec 2, 2021

Describe the bug
I have the following config and want to use the already registered serializer for the message text of the object:

public class ConfigTest extends OkaeriConfig {

    List<Message> messages = new ArrayList<>(List.of(
            new Message(text("Hi")),
            new Message(text("there!"))
    ));
}

@Data
public class Message {

    private final Component text;

    public Message(Component text) {
        this.text = text;
    }
}

final class MessageSerializer implements ObjectSerializer<Message> {

    @Override
    public boolean supports(Class<? super Message> type) {
        return Message.class.isAssignableFrom(type);
    }

    @Override
    public void serialize(Message object, SerializationData data) {
        data.add("text", object.getText());
    }

    @Override
    public Message deserialize(DeserializationData data, GenericsDeclaration generics) {
        return new Message(data.get("text", Component.class));
    }
}

final class MiniMessageComponentSerializer extends BidirectionalTransformer<String, Component> {

    private final MiniMessage parser = MiniMessage.miniMessage();

    @Override
    public GenericsPair<String, Component> getPair() {
        return new GenericsPair<>(GenericsDeclaration.of(String.class), GenericsDeclaration.of(Component.class));
    }

    @Override
    public Component leftToRight(final @NonNull String data, final @NonNull SerdesContext serdesContext) {
        return parser.deserialize(data);
    }

    @Override
    public String rightToLeft(final @NonNull Component data, final @NonNull SerdesContext serdesContext) {
        return parser.serialize(data);
    }
}

@PluginMain
public class TemplatePlugin extends JavaPlugin {

    @Getter
    @Accessors(fluent = true)
    private ConfigTest config;

    public TemplatePlugin() {
    }

    public TemplatePlugin(
            JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file) {
        super(loader, description, dataFolder, file);
    }

    @Override
    public void onEnable() {
        loadConfig();
    }

    private void loadConfig() {
        this.config = ConfigManager.create(ConfigTest.class, config -> config
                .withConfigurer(new YamlBukkitConfigurer(), new SerdesBukkit(), new SerdesCommons(), new ExamplePack())
                .withBindFile("config.yml")
                .saveDefaults()
                .load(true));
    }
}

To Reproduce
See the following repository with a failing test: https://github.com/sVoxelDev/okaeri-nested-serialization-bug

Expected behavior
The serializers should leverage already existing serializers.

@dasavick dasavick added bug Something isn't working good first issue Good for newcomers and removed bug Something isn't working labels Dec 2, 2021
@dasavick
Copy link
Member

dasavick commented Dec 2, 2021

My memory was a little rusty but thanks to your example project I was able to figure this out again quickly. In the cases where inheritance occurs, intended serialization type shall be provided via SerializationData typed methods.

Replace:

data.add("text", object.getText());

With:

data.add("text", object.getText(), Component.class);

Also take a look for other typed methods, for collections, maps, etc.: https://github.com/OkaeriPoland/okaeri-configs/blob/master/core/src/main/java/eu/okaeri/configs/serdes/SerializationData.java

Note third section of typed add method:

    /**
     * Adds value to the serialization data under specific key.
     * Provided value is simplified using attached Configurer.
     * <p>
     * This method allows to narrow target simplification type
     * and is recommended to be used with non-primitive classes.
     * <p>
     * Specifying target simplification type allows to make sure
     * correct serializer is used, e.g. interface type instead
     * of some implementation type that would otherwise inferred.
     *
     * @param key       target key
     * @param value     target value
     * @param valueType type of value for simplification process
     * @param <T>       type of value
     */
    public <T> void add(@NonNull String key, Object value, @NonNull Class<T> valueType) {
        GenericsDeclaration genericType = GenericsDeclaration.of(valueType);
        this.add(key, value, genericType);
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers invalid This doesn't seem right
Projects
None yet
Development

No branches or pull requests

2 participants