#c# #.net #json.net
#c# #.net #json.net
Вопрос:
Я хочу десериализовать документ JSON, который содержит объекты одного и того же типа User, представленные двумя различными способами: как полное представление объекта или как ссылка на существующий пользовательский объект по имени:
[
{
"User": "SomeUser"
},
{
"User": {
"Login": "SomeOtherUser",
"Active": true
}
}
]
Легко написать конвертер, который обрабатывает пользовательские объекты, на которые ссылаются по имени:
class User
{
public string Id;
public string Login;
public bool Active;
}
class Document
{
public User User;
}
class UserConverter : JsonConverter
{
public UserConverter(Dictionary<string, User> users)
{
_users = users;
}
public override bool CanConvert(Type objectType)
{
var res = typeof(User).IsAssignableFrom(objectType);
return res;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var name = ((User)value)?.Login;
writer.WriteValue(name);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var name = reader.Value?.ToString();
if (string.IsNullOrEmpty(name))
return null;
_users.TryGetValue(name, out var res);
return res;
}
readonly Dictionary<string, User> _users;
}
// ....
static void Test2()
{
var settings = new JsonSerializerSettings
{
MissingMemberHandling = MissingMemberHandling.Error,
Converters =
{
new UserConverter(new Dictionary<string, User> { { "SomeUser", new User() }})
}
};
var data = JsonConvert.DeserializeObject<List<Document>>("[{"User": "SomeUser"}, {"User": {"Login": "SomeUser","Active": true}}]", settings);
}
Однако это приводит к ошибкам десериализации при обнаружении полных пользовательских объектов: «Newtonsoft.Json.Исключение JsonSerializationException: «Не удалось найти элемент «Login» для объекта типа «Document». Путь ‘[1].Пользователь.Вход ‘»
Есть идеи, как заставить его поддерживать оба?
Комментарии:
1. Я не понимаю, почему вы кэшируете пользователей в словаре. Это не имеет отношения к вопросу и не является потокобезопасным, как реализовано.
2. Вы уверены, что ссылка всегда будет отображаться после полного представления объекта в файле? Кроме того, как это
User
выглядит? Есть ли у него общедоступный конструктор без параметров?3. Что за ошибка появляется?
4. Кроме того, при сериализации ваш текущий конвертер всегда будет записывать имя пользователя и никогда не будет записывать полное представление объекта. Это то, чего вы хотите?
5. @X39 смотрите обновление