Почему 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 о любой помощи. Я относительно новичок в С# - и это действительно вопрос любопытства больше, чем что-либо в этом пункте.
Ответы
Ответ 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 имеет доступ к константам.
подсказка шляпы здесь