Почему я не могу сериализовать свойство, которое имеет частный сеттер - PullRequest
1 голос
/ 18 мая 2019

Я использую ядро ​​dotnet 2.1 и создал помощника для сериализации из и в JSON.Он построен на System.Runtime.Serialization.Json, который поставляется с ядром dotnet.

Я не хочу использовать библиотеку 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, но это ничего не меняет.

Да, я могу редактировать свои классы, чтобы они были полностью открытыми, но я этого не понимаю, поэтомуВыкладываю здесь, если у кого-нибудь есть идея.

Спасибо

1 Ответ

3 голосов
/ 18 мая 2019

Когда вы используете System.Runtime.Serialization без каких-либо аннотаций, он игнорирует свойства, которые нельзя установить, и сериализует все открытые члены данного типа, которые могут быть сериализованы и десериализованы.

Однако, если вы пойдете на явное объявление о том, что он должен сериализовать, он будет работать:

[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"
  }
}
...