Подтвердить что ты не робот

Почему JSON.Net не может сериализовать переменные static или const?

Мне не удалось найти ответ на это где угодно, но когда я пытаюсь сериализовать структуру или класс со статическими или константными переменными-членами, они по умолчанию не сериализуются. Если я попытаюсь принудительно выполнить сериализацию, установив MemberSerialization.OptIn, я получаю сообщение об ошибке.

ех.

[JsonObject(MemberSerialization.OptIn)]
public class Test
{    
    [JsonProperty]
    public int x = 1;

    [JsonProperty]
    public static int y = 2;
}

Если я попытаюсь сериализовать этот класс с помощью:

Test t = new Test();
string s = JsonConvert.SerializeObject( t );

Я получаю сообщение об ошибке Error getting value from 'y' on 'Test'. То же самое происходит, если y const.

Моя теория заключается в том, что значения static и const хранятся где-то особенным в памяти, и по какой-то причине сериализатор Json умирает, пытаясь получить к ним доступ. Это все-таки догадка, и я ничего не вижу в С# Reference for Static о любой помощи. Я относительно новичок в С# - и это действительно вопрос любопытства больше, чем что-либо в этом пункте.

4b9b3361

Ответ 1

Он может, конечно, сериализовать статическую переменную, если захочет. Сериализация выполняется путем проверки объектов и типов с помощью API Reflection, и эти API позволяют вам "ничего" - нет технической причины, по которой эти значения не могут быть сериализованы.

Однако существует логическая причина не поддерживать это по умолчанию: это не имеет большого смысла. Вы сериализуете экземпляр, а члены static или const не являются логически частью экземпляра, а класса в целом.

Тем не менее, вы все равно можете сериализовать член static, если это свойство:

[JsonProperty]
public static int y { get; set; } // this will be serialized

И, конечно, вы можете полностью переопределить поведение сериализатора, создав пользовательский JsonConverter.

Ответ 2

Как и в Json.NET 6.0.4, статические и константные переменные-члены, а также статические свойства будут сериализованы при маркировке [JsonProperty]. Из примечания к выпуску:

  • Исправить - Исправлены статические поля сериализации

Таким образом, сериализуем следующий класс:

[JsonObject(MemberSerialization.OptIn)]
public class Test
{    
    [JsonProperty]
    int x = 1;

    [JsonProperty]
    static int y = 2;

    [JsonProperty]
    const int z = 333;
}

Производит {"x":1,"y":2,"z":333}. Пример fiddle.

Ответ 3

Если вам нужен статический член (или const) для сериализации в каждом экземпляре, вы можете использовать частный аксессуар на уровне экземпляра в качестве обходного пути:

[JsonObject(MemberSerialization.OptIn)]
public class Test
{
    [JsonProperty]
    public int x = 1;

    // static member we want serialized with each instance
    public static int y = 2;

    // private accessor to allow Json.net to serialize the static member
    [JsonProperty("y")]
    private int y1 { get { return y; } }
}

Если вам нужно десериализовать этот класс, этот подход не позволит Json.Net перезаписывать статический член, сохраняя при этом свой собственный код, если это необходимо.

Ответ 4

Попробуйте следующее:

using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;

public static string SerializeStaticClass(System.Type a_Type)
{
        var TypeBlob = a_Type.GetFields().ToDictionary(x => x.Name, x => x.GetValue(null));
        return JsonConvert.SerializeObject(TypeBlob);
}

Я сделал это для сериализации всех наших статических констант класса в JS файле, а затем связал этот файл с приложением angular. Вы присоединяете сгенерированные объекты js к $rootScope, и весь код angular имеет доступ к константам.

подсказка шляпы здесь