我有一个非常不理想的情况,要求我反序列化JSON,其中值是JSON.NET的字段名称。假设我具有以下结构正确的JSON:
{ "name": "tugberk", "roles": [ { "id": "1", "name": "admin" }, { "id": "2", "name": "guest" } ] }
使用JSON.NET将其反序列化为CLR对象非常容易:
class Program { static void Main(string[] args) { var camelCaseSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }; var text = File.ReadAllText("user_normal.txt"); var obj = JsonConvert.DeserializeObject<User>(text, camelCaseSettings); } } public class User { public string Name { get; set; } public Role[] Roles { get; set; } } public class Role { public int Id { get; set; } public string Name { get; set; } }
但是,在当前情况下,我有以下可怕的JSON,就值而言,它等效于上述JSON:
{ "name": "tugberk", "roles": { "1": { "name": "admin" }, "2": { "name": "guest" } } }
如您所见,rolesfield不是数组。这是一个包含其他值作为对象的对象,其唯一键作为其字段名称(这太可怕了)。User使用JSON.NET 将JSON反序列化为上述类的最佳方法是什么?
roles
User
您可以创建一个JsonConverter序列化/反序列化的自定义Role[]。然后,您可以像这样装饰您的Roles媒体资源JsonConverterAttribute:
JsonConverter
Role[]
Roles
JsonConverterAttribute
public class User { public string Name { get; set; } [JsonConverter(typeof(RolesConverter))] public Role[] Roles { get; set; } }
在转换器类中,您可以读取一个对象并返回一个数组。您的转换器类可能如下所示:
class RolesConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(Role[]); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // deserialize as object var roles = serializer.Deserialize<JObject>(reader); var result = new List<Role>(); // create an array out of the properties foreach (JProperty property in roles.Properties()) { var role = property.Value.ToObject<Role>(); role.Id = int.Parse(property.Name); result.Add(role); } return result.ToArray(); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } }