Json.NET — члены типа значения не десериализуются?

Я играл с Json.NET, и мне это очень нравится. Однако я столкнулся с проблемой при десериализации объектов с элементами типа значения. Например, рассмотрим этот код:

public struct Vector
{
    public float X;
    public float Y;
    public float Z;

    public override string ToString()
    {
        return string.Format("({0},{1},{2})", X, Y, Z);
    }
}

public class Object
{
    public Vector Position;
}

class Program
{
    static void Main(string[] args)
    {
        var obj = new Object();
        obj.Position = new Vector { X = 1, Y = 2, Z = 3 };

        var str = JsonConvert.SerializeObject(obj);

        Console.WriteLine(str); // {"Position":{"X":1.0,"Y":2.0,"Z":3.0}}

        obj = JsonConvert.DeserializeObject<Object>(str);

        Console.WriteLine(obj.Position); // (0,0,0)

        Console.ReadKey(true);
    }
}

Позиция сериализуется правильно, но не восстанавливается при десериализации. Интересно, что следующий код работает так, как ожидалось.

class Program
{
    static void Main(string[] args)
    {
        var vec = new Vector { X = 1, Y = 2, Z = 3 };

        var str = JsonConvert.SerializeObject(vec);

        Console.WriteLine(str); // {"X":1.0,"Y":2.0,"Z":3.0}

        vec = JsonConvert.DeserializeObject<Vector>(str);

        Console.WriteLine(vec); // (1,2,3)

        Console.ReadKey(true);
    }
}

Как видите, вектор правильно сериализуется/десериализуется сам по себе. Есть ли простое решение для первого сценария, или мне нужно создать что-то вроде собственного конвертера?


person kloffy    schedule 30.09.2010    source источник
comment
Определение класса с именем Object вызывает проблемы.   -  person JaredPar    schedule 01.10.2010
comment
Я согласен, но я могу с уверенностью сказать, что это не источник проблемы здесь.   -  person kloffy    schedule 01.10.2010


Ответы (1)


У вас есть два варианта.

  1. Измените структуру Vector на класс
  2. Или изменить:

    obj = JsonConvert.DeserializeObject<Object>(str);
    

    to

    obj = JsonConvert.DeserializeObject<Object>(str, new JsonSerializerSettings{ ObjectCreationHandling = ObjectCreationHandling.Replace});
    
person Matthew Manela    schedule 01.10.2010
comment
Векторная структура предоставляется библиотекой, поэтому первое предложение не вариант, но второе сработало. Интересно, сколько работы потребуется, чтобы заставить Json.NET знать о типах значений и делать то, что ObjectCreationHandling.Replace делает с ними по умолчанию. (Кроме того, PreserveReferencesHandling.All не имеет особого смысла и для типов значений, поэтому нет необходимости давать им $id.) - person kloffy; 01.10.2010