Как десериализовать структуру только для чтения с помощью конструктора, который принимает структуру только для чтения в качестве входного параметра? - PullRequest
0 голосов
/ 12 мая 2018

У меня есть структура readonly (Outer), которая имеет свойство struct readonly (Inner), которое передается в конструктор как параметр in, чтобы избежать одной копии при вызове конструктора.Попытка десериализации Outer приводит к путанице в Json.Net параметром in:

using System;
using Newtonsoft.Json;

namespace DeserializeTest
{
    public readonly struct Inner
    {
        [JsonConstructor]
        public Inner(int i) => I = i;

        public int I { get; }
    }

    public readonly struct Outer
    {
        [JsonConstructor]
        public Outer(in Inner inner) => Inner = inner;

        public Inner Inner { get; }
    }

    public class Program
    {
        public static void Main()
        {
            Console.WriteLine("Environment version: " + Environment.Version);
            Console.WriteLine("Json.NET version: " + typeof(JsonSerializer).Assembly.FullName);
            Console.WriteLine();

            try
            {
                var originalOuter = new Outer(new Inner(1));
                var json = JsonConvert.SerializeObject(originalOuter);
                var newOuter = JsonConvert.DeserializeObject<Outer>(json);
                Assert.IsTrue(originalOuter.Inner.I == newOuter.Inner.I);
                Console.WriteLine(json);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed with unhandled exception: ");
                Console.WriteLine(ex);
                throw;
            }
        }
    }

    public class AssertionFailedException : Exception
    {
        public AssertionFailedException(string s) : base(s) { }
    }

    public static class Assert
    {
        public static void IsTrue(bool value)
        {
            if (!value)
            {
                throw new AssertionFailedException("failed");
            }
        }
    }
}

Это приводит к следующему выводу:

Environment version: 4.0.30319.42000
Json.NET version: Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed

Unhandled Exception: Newtonsoft.Json.JsonSerializationException: Unable to find a constructor to use for type DeserializeTest.Inner&. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path 'Inner.I', line 1, position 14.
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, String id, Boolean& createdFromNonDefaultCreator)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
   at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
   at DeserializeTest.Program.Main() in e:\projects\DeserializeTest\DeserializeTest\Program.cs:line 31
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...