I have the following code, taken from https://learn.microsoft.com/En-Us/dotnet/standard/serialization/system-text-json/custom-contracts#example-serialize-private-fields. It works fine to serialize the fields of Brains.Brain, but when deserializing, the instance created has (a, b, c, d) = (2, 0, 4, 4) when it should be (2, 3, 4, 7). I’ve tried finding more on how to use a Json constructor, but haven’t been able to find much.
Would someone be able to direct me to if it is on the microsoft documentation (although I haven’t found it); somewhere else where it is documented; or some example code on how I should be using it or something else which solves this problem.
using System.IO;
using System.Linq;
using System.Text.Json;
//
using System.Reflection;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace BinaryFiles
{
class Program
{
static void Main(string[] args)
{
Brains.Brain b = new(3);
Type btype = typeof(Brains).GetNestedTypes().Where(brain => (brain.GetInterface("IBrain") != null)).ToArray()[0];
Loader.Save("test", b, btype);
b.test();
IBrain newB = Loader.Load("test", btype);
newB.test();
}
}
internal interface IBrain
{
public void test();
}
class Brains {
[JsonIncludePrivateFields]
public class Brain : IBrain
{
private int a = 2;
private int b;
public int c = 4;
public int d;
/*
[JsonConstructor]
public Brain(int a, int b, int c, int d) =>
(this.a, this.b, this.c, this.d) = (a, b, c, d);
*/
public Brain(int B)
{
this.b = B;
this.d = B + 4;
}
public void test()
{
Console.WriteLine($"{a} {b} {c} {d}");
}
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class JsonIncludePrivateFieldsAttribute : Attribute { }
internal static class Loader
{
static void AddPrivateFieldsModifier(JsonTypeInfo jsonTypeInfo)
{
if (jsonTypeInfo.Kind != JsonTypeInfoKind.Object)
return;
if (!jsonTypeInfo.Type.IsDefined(typeof(JsonIncludePrivateFieldsAttribute), inherit: false))
return;
foreach (FieldInfo field in jsonTypeInfo.Type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic))
{
JsonPropertyInfo jsonPropertyInfo = jsonTypeInfo.CreateJsonPropertyInfo(field.FieldType, field.Name);
jsonPropertyInfo.Get = field.GetValue;
jsonPropertyInfo.Set = field.SetValue;
jsonTypeInfo.Properties.Add(jsonPropertyInfo);
}
}
public static void Save(string fileName, IBrain brain, Type brainType)
{
var options = new JsonSerializerOptions
{
IncludeFields = true,
WriteIndented = true,
TypeInfoResolver = new DefaultJsonTypeInfoResolver
{
Modifiers = { AddPrivateFieldsModifier }
}
};
Console.WriteLine(JsonSerializer.Serialize(brain, brainType, options));
File.WriteAllText(fileName + ".json", JsonSerializer.Serialize(brain, options));
}
public static IBrain Load(string fileName, Type brainType)
{
var options = new JsonSerializerOptions
{
IncludeFields = true,
WriteIndented = true,
TypeInfoResolver = new DefaultJsonTypeInfoResolver
{
Modifiers = { AddPrivateFieldsModifier }
}
};
return (IBrain)JsonSerializer.Deserialize(File.ReadAllText(fileName + ".json"), brainType, options);
}
}
}```
2
Answers
Not sure what I changed, but it works now for some reason? Edit: It was adding brainType to the serializer.
Not sure what you did wrong but I managed to make it work this (simple) way:
and then: