如何使用 JSON.NET 将 JSON 数组中的对象名称用作 属性 值?
How can I use the object name in a JSON array as a property value using JSON.NET?
我有以下 JSON 块(从完整的 JSON 中提取以简化问题):
"statistics": [
{
"Strength": {
"min": 16,
"max": 20
}
},
{
"Dexterity": {
"min": 16,
"max": 20
}
}]
我想将 "statistics" 数组反序列化为 "Statistic" 对象的 C# 数组,但我可以"t find how to do it... The key of each statistic object can be anything : "Strength","Luck","Dexterity" 等等,每个键都是唯一的。
C# 数据对象应该是这样的:
public class Container
{
public Statistic[] Statistics { get; set; }
}
public class Statistic
{
//Contains the name of the statistic
public string Name { get; set; }
public int Min { get; set; }
public int Max { get; set; }
}
也许我可以通过删除 Name
属性 并创建所有可能的 类 统计信息来使用某种多态性,但这会破坏我的代码的适应性。
非常感谢。
给定提供的 JSON,我们不能直接使用 Dictionary
结构,这是因为我们有一个对象数组,其中每个对象都有 Statistic
名称作为属性 名称(虽然它应该是一个名为 Name
的 属性 的值)
为避免处理自定义转换器,这里有一个快速(非生产就绪!)解决方案,可以为您提供一个良好的起点。
这个想法是将其反序列化为 dynamic
,然后将 statistics
对象提取为 JArray
并从那里构建结果结构。
请注意,我没有检查任何内容是否为 null,因此只要输入格式正确(您需要来自 NuGet 的 Newtonsoft.Json
),它就可以工作。
using System;
using System.Linq;
using Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Whosebug
{
internal class Program
{
private static readonly string _inputJson =
@"
{
""statistics"": [
{
""Strength"": {
""min"": 16,
""max"": 20
}
},
{
""Dexterity"": {
""min"": 16,
""max"": 20
}
}]
}
";
private static void Main(string[] args)
{
var tempObject = JsonConvert.DeserializeObject<dynamic>(_inputJson).statistics as JArray;
var result = new Container
{
Statistics = tempObject.Select(obj =>
{
var token = obj.First as JProperty;
var stats = token.Value;
return new Statistic
{
Name = token.Name,
Min = Convert.ToInt32((stats["min"] as JValue).Value),
Max = Convert.ToInt32((stats["max"] as JValue).Value)
};
}).ToArray()
};
foreach (var stat in result.Statistics) Console.WriteLine($"{stat.Name} = ({stat.Min}, {stat.Max})");
}
}
}
namespace Models
{
public class Container
{
public Statistic[] Statistics { get; set; }
}
public class Statistic
{
//Contains the name of the statistic
public string Name { get; set; }
public int Min { get; set; }
public int Max { get; set; }
}
}
这是我得到的输出:
Strength = (16, 20)
Dexterity = (16, 20)
您可以使用简单的 JsonConverter
为您的 Statistic
class 处理这个棘手的 JSON,如下所示:
class StatisticConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Statistic);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
JProperty prop = jo.Properties().First();
Statistic stat = new Statistic
{
Name = prop.Name,
Min = (int)prop.Value["min"],
Max = (int)prop.Value["max"]
};
return stat;
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
要使用它,请将 [JsonConverter]
属性添加到 Statistic
class,它应该会按预期工作:
[JsonConverter(typeof(StatisticConverter))]
public class Statistic
{
public string Name { get; set; }
public int Min { get; set; }
public int Max { get; set; }
}
这是一个工作演示:https://dotnetfiddle.net/H7wR0g
如果您不能(或不想)将属性添加到 Statistic
class,您也可以通过将其传递给 DeserializeObject
方法来使用转换器,例如这个:
var container = JsonConvert.DeserializeObject<Container>(json, new StatisticConverter());
Fiddle: https://dotnetfiddle.net/UTLzBk
我有以下 JSON 块(从完整的 JSON 中提取以简化问题):
"statistics": [
{
"Strength": {
"min": 16,
"max": 20
}
},
{
"Dexterity": {
"min": 16,
"max": 20
}
}]
我想将 "statistics" 数组反序列化为 "Statistic" 对象的 C# 数组,但我可以"t find how to do it... The key of each statistic object can be anything : "Strength","Luck","Dexterity" 等等,每个键都是唯一的。
C# 数据对象应该是这样的:
public class Container
{
public Statistic[] Statistics { get; set; }
}
public class Statistic
{
//Contains the name of the statistic
public string Name { get; set; }
public int Min { get; set; }
public int Max { get; set; }
}
也许我可以通过删除 Name
属性 并创建所有可能的 类 统计信息来使用某种多态性,但这会破坏我的代码的适应性。
非常感谢。
给定提供的 JSON,我们不能直接使用 Dictionary
结构,这是因为我们有一个对象数组,其中每个对象都有 Statistic
名称作为属性 名称(虽然它应该是一个名为 Name
的 属性 的值)
为避免处理自定义转换器,这里有一个快速(非生产就绪!)解决方案,可以为您提供一个良好的起点。
这个想法是将其反序列化为 dynamic
,然后将 statistics
对象提取为 JArray
并从那里构建结果结构。
请注意,我没有检查任何内容是否为 null,因此只要输入格式正确(您需要来自 NuGet 的 Newtonsoft.Json
),它就可以工作。
using System;
using System.Linq;
using Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Whosebug
{
internal class Program
{
private static readonly string _inputJson =
@"
{
""statistics"": [
{
""Strength"": {
""min"": 16,
""max"": 20
}
},
{
""Dexterity"": {
""min"": 16,
""max"": 20
}
}]
}
";
private static void Main(string[] args)
{
var tempObject = JsonConvert.DeserializeObject<dynamic>(_inputJson).statistics as JArray;
var result = new Container
{
Statistics = tempObject.Select(obj =>
{
var token = obj.First as JProperty;
var stats = token.Value;
return new Statistic
{
Name = token.Name,
Min = Convert.ToInt32((stats["min"] as JValue).Value),
Max = Convert.ToInt32((stats["max"] as JValue).Value)
};
}).ToArray()
};
foreach (var stat in result.Statistics) Console.WriteLine($"{stat.Name} = ({stat.Min}, {stat.Max})");
}
}
}
namespace Models
{
public class Container
{
public Statistic[] Statistics { get; set; }
}
public class Statistic
{
//Contains the name of the statistic
public string Name { get; set; }
public int Min { get; set; }
public int Max { get; set; }
}
}
这是我得到的输出:
Strength = (16, 20)
Dexterity = (16, 20)
您可以使用简单的 JsonConverter
为您的 Statistic
class 处理这个棘手的 JSON,如下所示:
class StatisticConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Statistic);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
JProperty prop = jo.Properties().First();
Statistic stat = new Statistic
{
Name = prop.Name,
Min = (int)prop.Value["min"],
Max = (int)prop.Value["max"]
};
return stat;
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
要使用它,请将 [JsonConverter]
属性添加到 Statistic
class,它应该会按预期工作:
[JsonConverter(typeof(StatisticConverter))]
public class Statistic
{
public string Name { get; set; }
public int Min { get; set; }
public int Max { get; set; }
}
这是一个工作演示:https://dotnetfiddle.net/H7wR0g
如果您不能(或不想)将属性添加到 Statistic
class,您也可以通过将其传递给 DeserializeObject
方法来使用转换器,例如这个:
var container = JsonConvert.DeserializeObject<Container>(json, new StatisticConverter());
Fiddle: https://dotnetfiddle.net/UTLzBk