为什么我不能序列化具有私有设置程序(C#,json)的属性

 收藏

我使用的是dotnet core 2.1,并提供了一个帮助程序从JSON序列化到JSON。 它基于dotnet核心附带的System.Runtime.Serialization.Json构建。

由于某些原因,我不想使用JSON.NET库(在这里无关紧要)

我遇到了一个我不明白的错误, 这是我制作的Helper类(我刚刚离开了ToJson方法,因为这是发生问题的方法)

public static class JsonUtils
{
    private static readonly DataContractJsonSerializerSettings _jsonSettings = new DataContractJsonSerializerSettings
    {
        UseSimpleDictionaryFormat = true,
        SerializeReadOnlyTypes = true,
        EmitTypeInformation = EmitTypeInformation.Never
    };

    public static string ToReadableJson<T>(T o)
    {
        string res = null;

        try
        {
            using (var ms = new MemoryStream())
            using (var writer = JsonReaderWriterFactory.CreateJsonWriter(ms, Encoding.UTF8, true, true, "  "))
            {
                var serializer = new DataContractJsonSerializer(typeof(T), _jsonSettings);
                serializer.WriteObject(writer, o);
                writer.Flush();

                ms.Position = 0;

                using (var sr = new StreamReader(ms))
                {
                    res = sr.ReadToEnd();
                }
            }
        }
        catch
        { }

        return res;
    }
}

一切工作正常,直到我最近注意到,如果某些对象的属性具有非公共设置器,则将其忽略。我不明白为什么设置器必须是公开的,只是应该读取数据进行序列化,对吗?

这是一些要测试的代码:

public class TestSubObject
{
    public string Property { get; set; } = "Bar";
}

public class TestObject
{
    public TestSubObject Sub { get; set; }
    public string Property { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var o = new TestObject
        {
            Property = "Foo",
            Sub = new TestSubObject()
        };

        string json = JsonUtils.ToReadableJson<TestObject>(o);
        Console.WriteLine(json);

        Console.Read();
    }
}

在此示例中,我只有一个根对象(TestObject),该对象具有另一个复杂对象作为属性(TestSubObject)

在这种情况下,它可以工作:

OK

然后,如果我将TestSubObject.Property设置器从公共更改为私有,它将不再起作用。 (在我的实际情况下,该类在另一个具有“内部”设置的程序集中)

NOTOK

我的子财产消失了。

如您所见,我检查了DataContractJsonSerializerSettings并已将SerializeReadOnlyTypes设置为true,但这并没有改变。

是的,我可以将我的课程编辑为完全公开,但是我不明白这一点,因此如果有人有想法,我可以在此处发布。

谢谢

回复
  • 胖子 回复

    When you use System.Runtime.Serialization without any annotations it will ignore properties that can't be set and serialize all public members of given type that can be serialized and deserialized.

    但是,如果您明确声明应序列化的内容,则可以使用:

    [DataContract]
    public class TestSubObject
    {
        [DataMember]
        public string Property { get; private set; } = "Bar";
    }
    
    [DataContract]
    public class TestObject
    {
        [DataMember]
        public TestSubObject Sub { get; set; }
        [DataMember]
        public string Property { get; set; }
    }
    

    输出:

    {
      "Property": "Foo",
      "Sub": {
        "Property": "Bar"
      }
    }