TheElectronWill / night-config

Powerful java configuration library for toml, yaml, hocon, json and in-memory configurations. Serialization/deserialization framework.
GNU Lesser General Public License v3.0
233 stars 27 forks source link

How to use @Conversion with List fields #169

Open NeusFear opened 5 months ago

NeusFear commented 5 months ago

I have a section of a TOML file like this:

[dependencies]
required = ["examplemod:1.0.0"]
optional = ["anothermod:1.0.0"]

which I wish to parse with an ObjectConverter. I've attempted the below code to do so, but I get an error to do with not being able to case ArrayList to Pair, which I suspect to be because the field is a list and the conversion is just for a single entry in that list.

See applicable section of converter code:

    public static class ModDependencies {
        //A Pair defined as <Namespace, Version>
        @Conversion(VersionToStringConverter.class)
        List<Pair<String, Version>> required;
        @Conversion(VersionToStringConverter.class)
        List<Pair<String, Version>> optional;
    }

    static class VersionToStringConverter implements Converter<String, Pair<String, Version>> {

        @Override
        public String convertToField(Pair<String, Version> stringVersionPair) {
            return stringVersionPair.getValue0() + ":" + stringVersionPair.getValue1();
        }

        @Override
        public Pair<String, Version> convertFromField(String s) {
            String[] split = s.split(":");
            return new Pair<>(split[0], Version.parse(split[1]));
        }
    }

What is the correct way to parse a list of items to an object with an ObjectConverter when the items in the list need to be converted by a Converter?

TheElectronWill commented 5 months ago

Hello!

I'm afraid that this is not directly supported by @Conversion. The new serde framework will vastly improve this, but in the meantime, I can think of the following workaround: introduce a new class that contains the pair:

public static class VersionPair {
        @Conversion(VersionToStringConverter.class) // <- @Conversion here
        Pair<String, Version> value;
}
public static class ModDependencies {
        List<VersionPair> required; // <- not here (let night-config's ObjectConverter do its work with the list)
}
NeusFear commented 5 months ago

That seems like it would work, but when I try to implement something like this I get an error to do with not expecting an element of type String in collection of objects. Here is the full converter based on your reccomendations: https://gist.github.com/NeusFear/4f5159ee7ce9beaa4911a2e1ac551c4a

And The error:

Exception in thread "main" com.electronwill.nightconfig.core.conversion.InvalidValueException: Unexpected element of type class java.lang.String in collection of objects
    at com.electronwill.nightconfig.core.conversion.ObjectConverter.convertConfigsToObject(ObjectConverter.java:417)

Any idea what might be causing this one?

NeusFear commented 5 months ago

I suppose you will also want the whole toml file since I sent the whole parser, The rest of it was working so I don't expect it to be an issue with the rest of it, but for your reference here is this:

[identity]
namespace = "testmod"
name = "Test Mod"
description = "A test mod to show the features of the TVE modding system & inherent modding api."
version = "1.0.0-alpha.1"

[authors]
creators = ["NeusFear"]
contributors = ["Another"]

[dependencies]
required = ["anothermod:1.0.0"]
optional = ["examplemod:1.0.0"]
TheElectronWill commented 5 months ago

Oh, interesting :thinking: I'll have to run some tests on this one. Does it work on master?

NeusFear commented 3 months ago

Sorry for the late response, I guess I never got a notification. It does not work on 3.8.0