I am trying to serialize and deserialize a class (say A) into Json.
The class has multiple properties (say X1, X2, X3) which are object instances (of class X) which contains large lists.
public class A
{
public X X1 { get; set; }
public X X2 { get; set; }
public X X3 { get; set; }
}
public class X
{
// This should request the serializer to put this into a separate file rather than within the parent's json
[JsonIgnore]
public bool SplitJson { get; set; }
public List<Y> LargeList { get; set; }
}
public class Y
{
public List<object> AnotherList { get; set; }
}
public class Temp
{
public static void JsonTest()
{
A a = new()
{
X1 = new()
{
LargeList =
[
new()
{
AnotherList = ["placeholder"]
}
],
SplitJson = true
},
X2 = new()
{
LargeList =
[
new()
{
AnotherList = ["dummy"]
}
],
SplitJson = true
},
X3 = new()
{
LargeList =
[
new()
{
AnotherList = ["text"]
}
]
}
};
JsonSerializerOptions options = new() { WriteIndented = true };
Debug.WriteLine(JsonSerializer.Serialize(a, options));
}
}
While I can serialize those instances (of class X) individually and load them into my main class (A), I need a way to serialize class A into Json in such a way that its properties (X1 & X2) are serialized into relative file paths ("X1.json" & "X2.json") only when they request so.
For example: This is the normal output
{
"X1": {
"LargeList": [
{
"AnotherList": [
"placeholder"
]
}
]
},
"X2": {
"LargeList": [
{
"AnotherList": [
"dummy"
]
}
]
},
"X3": {
"LargeList": [
{
"AnotherList": [
"text"
]
}
]
}
}
What I need is something like this:
{
"X1": "X1.json",
"X2": "X2.json",
"X3": {
"LargeList": [
{
"AnotherList": [
"text"
]
}
]
}
}
I need to control the serialization by means of a Boolean
property in class X
called SplitJson
. If enabled the serializer should serialize the instances of X
with SplitJson
set to true into relative paths. Then those instances of X of those properties should be serialized into the corresponding files. This should also work with deserialization.
Also, are there any ways to implement delayed (or async) setting of properties? I need the class A
to load first but the properties with relative paths to json files should not be deserialized until required. But the relative paths to the separate Jsons should be stored somewhere and must deserialize when needed.
2
Answers
@sinatr, Thank you so much for your guidance!
I was really confused with Json Serialization in
System.Text.Json
. I thought I would have to write my own converter to handle writing and reading all properties by myself and put into consideration of polymorphism and everything for this. But your approach of usingJsonConverterAttribute
on properties solved my confusion. If I had to make aJsonConverterFactory
or apply the attribute to the class, I would have to write and read the Json manually. But with this I can trick theJsonSerializer
to do all the work instead. I also figured out how to make it work with lists.That being said, I modified your approach to meet my criteria. Here is my code,
And here is the output:
And as to support delayed loading (that is due to async file operations in UWP). This converter will return an empty instance with only the json file path in
MetadataPath
.And this empty instance can then be populated with the loaded json whenever needed. Here is the code for the populate method: https://github.com/dotnet/runtime/issues/29538#issuecomment-1330494636
You can use json converters to customize produced json and perform custom steps (creating separate json-files in your case).
Just to get you started, here is a converter:
To pass file name into converter you need to create attribute yourself:
Now you can use attribute in your class:
And to test we serialize and deserialize:
The output:
And there should be 3 json-files near executable file.