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

Strange inlining behavior of TomlTable when serializing #89

Open
UliPlabst opened this issue Oct 8, 2024 · 3 comments
Open

Strange inlining behavior of TomlTable when serializing #89

UliPlabst opened this issue Oct 8, 2024 · 3 comments
Labels
enhancement New feature or request PR welcome User contribution/PR is welcome question Further information is requested

Comments

@UliPlabst
Copy link

Hello, first and foremost thank you for creating this library!
Today I switched from json to toml for our application config format because json makes it really hard to deal with comments. For us the use-case is really important that we can roundtrip the config like this:
Config string => deserialized model => change model, e.g. change a property => serialize to config again and save
Your library brought us almost there, comments are handled very well and roundtripped to the serialized output. But I noticed some strange behavior regarding when TomTable is serialized as inline object (key value pairs with brackets) and when as a proper table syntax (like [table]...).
Consider the following script (you can use roslynpad to test it)

#r "nuget: Tomlyn, 0.17.0"
using Tomlyn;

var toml = """
# Array = [ 0, 1, 2, 3, 4, 5, 6, 7 ]
[Map]
Key1 = "k1"
[Map2]
Key1 = "k1"
""".Trim();

var opts = new TomlModelOptions
{
    ConvertPropertyName = e => e
};
var model = Toml.ToModel(toml, null, opts);
var content = Toml.FromModel(model, opts);
Console.WriteLine(content);
//outputs this:
//# Array = [ 0, 1, 2, 3, 4, 5, 6, 7 ]
//[Map]
//Key1 = "k1"
//[Map2]
//Key1 = "k1"

toml = """
Array = [ 0, 1, 2, 3, 4, 5, 6, 7 ]
[Map]
Key1 = "k1"
[Map2]
Key1 = "k1"
""".Trim();
model = Toml.ToModel(toml, null, opts);
content = Toml.FromModel(model, opts);

Console.WriteLine(content);
//outputs this:
//Array = [0, 1, 2, 3, 4, 5, 6, 7]
//Map = { Key1 = "k1"}
//[Map2]
//Key1 = "k1"

toml = """
Array = [ 0, 1, 2, 3, 4, 5, 6, 7 ]
[Map]
Key1 = "k1"
# [Map2]
# Key1 = "k1"
""".Trim();
model = Toml.ToModel(toml, null, opts);
content = Toml.FromModel(model, opts);

Console.WriteLine(content);
//outputs this:
//Array = [0, 1, 2, 3, 4, 5, 6, 7]
//[Map]
//Key1 = "k1"
//# [Map2]
//# Key1 = "k1"

note that the inlining behavior of the TomlTable Map somehow depends on if Array is there or if Map2 is there. For my specific use case the 2nd output is undesirable, but is the output I get.
My question:
Is this by design or a bug in the inlining behavior? It would be really nice to have an option for configuring the inlining behavior from the outside. And it would be super useful for a configuration language to remember the SyntaxKind that the Node (in this case TomlTable) was created from such that it can serialize to the same SyntaxKind when serialized.
If you agree that these features would be useful I would be down to implement them and send a PR.

@xoofx xoofx added enhancement New feature or request PR welcome User contribution/PR is welcome question Further information is requested labels Oct 8, 2024
@xoofx
Copy link
Owner

xoofx commented Oct 8, 2024

It would be really nice to have an option for configuring the inlining behavior from the outside. And it would be super useful for a configuration language to remember the SyntaxKind that the Node (in this case TomlTable) was created from such that it can serialize to the same SyntaxKind when serialized.
If you agree that these features would be useful I would be down to implement them and send a PR.

I forgot the details about why there is this behavior, and currently don't have time to dig into these.

For runtime models, there is some infrastructure to attach some metadata to existing properties in https://github.com/xoofx/Tomlyn/blob/main/src/Tomlyn/Model/TomlPropertiesMetadata.cs and this is what is used for preserving comments with e.g the builtin TomlTable. There is a DisplayKind that should be doing what you are looking for, but it might not be fully implemented or there are caes that could be mishandled, but you can start from there. Sure PR welcome if you find out a good solution.

@UliPlabst
Copy link
Author

I looked into supporting my use-case but as it turns out TOML has a lot of ambiguity in it's grammar in how the same thing (like an object) can be written. This makes it really hard to write the logic for serialization if the custom formatting should be preserved.
So I decided to ditch TOML as config format and go back to JSON. I implemented my own JSON Library to support proper format and comment handling. This was more straight forward than it would be in TOML.

@xoofx
Copy link
Owner

xoofx commented Oct 13, 2024

I looked into supporting my use-case but as it turns out TOML has a lot of ambiguity in it's grammar in how the same thing (like an object) can be written

Agreed. When I initially wrote this library, I was appealed by the simplicity of TOML, but I have also discovered that it can become quickly more difficult to author compared to e.g XML/JSON. It works well for simple key/value pairs and simple sections (like original ini files), but when you start to use arrays, it's not amazing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request PR welcome User contribution/PR is welcome question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants