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

Support complex root structures #23

Open
shravan2x opened this issue May 17, 2020 · 4 comments
Open

Support complex root structures #23

shravan2x opened this issue May 17, 2020 · 4 comments

Comments

@shravan2x
Copy link
Owner

The KeyValues wiki states that statements like "#base" "panelBase.res" may be present in VDF files. Automatically executing import statements is out of scope for this library, but we should support these if possible. There may also be other root tokens like comments. One way to return these is as a IReadOnlyList<VToken>.

TODO:

  • Are such "complex" root structures common? Do any users rely on hacks to solve this problem?
  • Should this be a breaking change or an overload?
@ghost
Copy link

ghost commented Jul 28, 2021

Will be nice to have a Deserialization with a nested structures like in the "libraryfolders.vdf" where you can have multiple places where to look for games installed.

"libraryfolders"
{
"contentstatsid" "-1467807043615334209"
"1"
{
"path" "D:\SteamLibrary"
"label" "Data"
"mounted" "1"
"contentid" "6724898736848565524"
}
"2"
{
"path" "E:\SteamLibrary"
"label" "Data"
"mounted" "1"
"contentid" "6724898736848565524"
}
}

In this case having a class for the whole content will be something like that:

public class LibraryFolders
{
    public string ContentStatsId { get; set; }

    public IEnumerable<LibraryFolderSpecification> libraryFoldersSpecifications = new List<LibraryFolderSpecification>();
}

public class LibraryFolderSpecification
{
    public string Path { get; set; }
    public string Label { get; set; }
    public int Mounted { get; set; }
    public UInt64 ContentId { get; set; }
}

So when we deserialize that content the objects will be automatically populated.

@shravan2x
Copy link
Owner Author

This is a tricky issue to solve as there isn't a way to check if the keys 1,2,... are elements of an array or proper keys by themselves. We could have an attribute on a list property that tells the library to put all array elements into it but that's quite a bit of work (since we currently rely on an intermediate JSON conversion step for model deserialization)

I think it may be best to do this logic using LINQ when you're sure it'll be an array:

VProperty root = VdfConvert.Deserialize(input);
JObject rootObj = (JObject) root.Value.ToJson();
LibraryFolders libraryFolders = new LibraryFolders
{
    ContentStatsId = rootObj["contentstatsid"]!.Value<string>()!,
    libraryFoldersSpecifications = Enumerable
        .Range(1, rootObj.Children<JProperty>().Select(x => x.Name).Where(x => Int32.TryParse(x, out _)).Select(x => Int32.Parse(x)).Max())
        .Select(x => rootObj[x.ToString()]!.ToObject<LibraryFolderSpecification>()!)
        .ToList()
};

This deserialized neatly as
image

@ZzZombo
Copy link

ZzZombo commented Nov 18, 2023

The KeyValues wiki states that statements like "#base" "panelBase.res" may be present in VDF files. Automatically executing import statements is out of scope for this library, but we should support these if possible. There may also be other root tokens like comments. One way to return these is as a IReadOnlyList<VToken>.

TODO:

  • Are such "complex" root structures common? Do any users rely on hacks to solve this problem?
  • Should this be a breaking change or an overload?

Sound scripts have multiple elements at the root scope, rather than one root element encompassing the rest.

@shravan2x
Copy link
Owner Author

@ZzZombo Could you share an example file?

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

No branches or pull requests

2 participants