我有以下代码,取自https://learn.microsoft.com/En-Us/dotnet/standard/serialization/system-text-json/custom-contracts#example-serialize-private-fields.序列化Brains.Brain的字段可以正常工作,但是在序列化时,创建的实例具有(a,b,c,d)=(2,0,4,4),而实际上应该是(2,3,4,7).我试着找到更多关于如何使用JSON构造函数的信息,但没有找到太多.

如果它在Microsoft文档上(尽管我还没有找到它),或者其他有文档记录的地方,或者一些关于我应该如何使用它的示例代码,或者其他解决这个问题的东西,有人能告诉我吗?

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);
        }
    }
}```

推荐答案

不确定我更改了什么,但出于某种原因,它现在起作用了? 编辑:它正在向序列化程序添加BrainType.

using System;
using System.IO;
using System.Linq;
//
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;

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;

            public Brain() // for use by deserializer
            {
                Console.WriteLine("called");
            }

            public Brain(int B)
            {
                this.b = B;
                this.d = B + 4;
                this.a = 1;
            }
            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));
            //JsonSerializer.SerializeToDocument();
            File.WriteAllText(fileName + ".json", JsonSerializer.Serialize(brain, brainType, options));
        }

        public static IBrain Load(string fileName, Type brainType)
        {
            var options = new JsonSerializerOptions
            {
                IncludeFields = true,
                WriteIndented = true,
                TypeInfoResolver = new DefaultJsonTypeInfoResolver
                {
                    Modifiers = { AddPrivateFieldsModifier }
                }
            };
            Console.WriteLine(File.ReadAllText(fileName + ".json"));
            return (IBrain)JsonSerializer.Deserialize(File.ReadAllText(fileName + ".json"), brainType, options);
        }
    }
}```

Csharp相关问答推荐

为什么xslWriter不总是按照xslWriterSet中指定的格式格式化该文档?

我可以 suppress 规则CS 9035一次吗?

如何使用CsvReader获取给定列索引的列标题?

在LINQ Where子句中使用新的DateTime

XUNIT是否使用测试数据的源生成器?

C#方法从AJAX调用接收NULL

C#EF Core WHERE IN LINQ FROM LIST WITH.CONTAINS不返回任何内容

在调整大小的控件上绘制

当用户右键单击文本框并单击粘贴时触发什么事件?

如何使用MoQ模拟Resources GroupCollection?

未找到任何HTTP触发器.成功部署Azure Functions Project后(c#)

我如何让我的秒表保持运行场景而不重置

数据库.Migrate在对接容器重启时失败

有条件地定义预处理器指令常量

这是否比决定是否使用ConfigureAWait(False)更好?

.NET Google Workspace API获取错误CS0266

C#中类库项目的源代码生成器

Blazor服务器项目中的Blazor/.NET 8/Web API不工作

仅在Blazor Web App中覆盖生产的基本路径(.NET8中的_Hosts.cshtml文件功能?)

将ValueTask发送给调用者