将 JSON 反序列化为 c# class
Deserializing JSON into c# class
我有一个 JSON 格式如下(来自 couchDB 视图)
{"rows":[
{"key":["2015-04-01","524","http://www.sampleurl.com/"],"value":1},
{"key":["2015-04-01","524","http://www.sampleurl2.com/"],"value":2},
{"key":["2015-04-01","524","http://www.sampleurl3.com"],"value":1}
]}
我需要创建一个 "service" 以从 couchDB 获取此数据并以有效的方式将其插入 SQL 服务器(用于生成报告..)。我的第一个赌注是将此 json 批量插入 SQL 服务器,如下所示:Bulk Insert from Generic List into SQL Server with minimum lines of code
问题是,如何将此 JSON 映射到 c# class?
直到现在,这就是我所做的:
public class Row
{
public List<string> key { get; set; }
public int value { get; set; }
}
public class RootObject
{
public List<Row> rows { get; set; }
}
var example = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(jsontext);
这给了我 "Rows" 的列表。每行都有一个键,每个键都是一个包含日期、Url 和数字的数组。
我可以遍历 "rows" 并自行创建对象,但这对我来说听起来不是很高效。此外,JSON 会很大,大约 5MB。
我想要的结构是这样的:
public class Click
{
public DateTime Date { get; set; }
public string Code { get; set; }
public string Url { get; set; }
public int Count { get; set; }
}
如何提取 "key" 数组并将其映射到单独的属性中。这样,我就不需要 for 循环了。
有什么想法吗?
给你。
public class Row
{
// Serialize/Deserialize the `key` into it's values.
public List<string> key { get { return new List<string>() { Date.ToString("yyyy-MM-dd"), Code, Url }; } set { Date = DateTime.Parse(value[0]); Code = value[1]; Url = value[2]; } }
// Serialize/Deserialize the `value` into `Count`.
public int value { get { return Count; } set { Count = value; } }
[ScriptIgnore]
public DateTime Date { get; set; }
[ScriptIgnore]
public string Code { get; set; }
[ScriptIgnore]
public string Url { get; set; }
[ScriptIgnore]
public int Count { get; set; }
public override string ToString()
{
return Date.ToString("yyyy-MM-dd") + ", " + Code + ", " + Url + ", " + Count;
}
}
public class RootObject
{
public List<Row> rows { get; set; }
}
public static void _Main(string[] args)
{
string json = "{\"rows\":[" +
"{\"key\":[\"2015-04-01\",\"524\",\"http://www.sampleurl.com/\"],\"value\":1}," +
"{\"key\":[\"2015-04-01\",\"524\",\"http://www.sampleurl2.com/\"],\"value\":2}," +
"{\"key\":[\"2015-04-01\",\"524\",\"http://www.sampleurl3.com\"],\"value\":1}" +
"]}";
var jss = new JavaScriptSerializer();
var example = jss.Deserialize<RootObject>(json);
foreach (Row r in example.rows)
{
Console.WriteLine(r.ToString());
}
}
它应该是不言自明的。如果您想让我详细说明,请询问。不过,这确实需要元素始终保持一致的顺序。
上面的输出:
2015-04-01, 524, http://www.sampleurl.com/, 1
2015-04-01, 524, http://www.sampleurl2.com/, 2
2015-04-01, 524, http://www.sampleurl3.com, 1
这种方法的明显好处是它的开销很低。它也很容易维护。这也意味着您显然可以在具有 ScriptIgnoreAttribute
的属性上提供 XmlIgnoreAttribute
,并且它还会生成并读取有效的序列化 XML.
注:我用的是System.Web.Script.Serialization.JavaScriptSerializer
。如果 JSON.NET
不使用 ScriptIgnoreAttribute
,则您必须应用它使用的任何属性。 (我从来没有用过JSON.NET
。)
另一个注意事项:我是针对 C#6.0
和 .NET 4.6
写的。您的结果可能会有所不同。
您可以为此创建自定义 JsonConverter
:
[JsonConverter(typeof(ClickConverter))]
public class Click
{
public DateTime Date { get; set; }
public string Code { get; set; }
public string Url { get; set; }
public int Count { get; set; }
}
public class ClickConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(Click).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var token = JToken.Load(reader);
if (token == null || token.Type == JTokenType.Null)
return null;
var click = (existingValue as Click ?? new Click());
var key = token["key"] as JArray;
if (key != null && key.Count > 0)
click.Date = (DateTime)key[0];
if (key != null && key.Count > 1)
click.Code = (string)key[1];
if (key != null && key.Count > 2)
click.Url = (string)key[2];
var value = token["value"];
if (value != null)
click.Count = (int)value;
return click;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
// Fill in with the opposite of the code above, if needed
var click = value as Click;
if (click == null)
writer.WriteNull();
else
serializer.Serialize(writer,
new
{
// Update the date string format as appropriate
// https://msdn.microsoft.com/en-us/library/8kb3ddd4%28v=vs.110%29.aspx
key = new string[] { click.Date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture), click.Code.ToString(CultureInfo.InvariantCulture), click.Url },
value = click.Count
});
}
}
public class RootObject
{
public List<Click> rows { get; set; }
}
将转换器直接应用于 class,您可以像往常一样(反)序列化:
var jsontext = @"{""rows"":[
{""key"":[""2015-04-01"",""524"",""http://www.sampleurl.com/""],""value"":1},
{""key"":[""2015-04-01"",""524"",""http://www.sampleurl2.com/""],""value"":2},
{""key"":[""2015-04-01"",""524"",""http://www.sampleurl3.com""],""value"":1}
]}";
var rows = JsonConvert.DeserializeObject<RootObject>(jsontext);
Debug.WriteLine(JsonConvert.SerializeObject(rows, Formatting.Indented));
我有一个 JSON 格式如下(来自 couchDB 视图)
{"rows":[
{"key":["2015-04-01","524","http://www.sampleurl.com/"],"value":1},
{"key":["2015-04-01","524","http://www.sampleurl2.com/"],"value":2},
{"key":["2015-04-01","524","http://www.sampleurl3.com"],"value":1}
]}
我需要创建一个 "service" 以从 couchDB 获取此数据并以有效的方式将其插入 SQL 服务器(用于生成报告..)。我的第一个赌注是将此 json 批量插入 SQL 服务器,如下所示:Bulk Insert from Generic List into SQL Server with minimum lines of code
问题是,如何将此 JSON 映射到 c# class?
直到现在,这就是我所做的:
public class Row
{
public List<string> key { get; set; }
public int value { get; set; }
}
public class RootObject
{
public List<Row> rows { get; set; }
}
var example = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(jsontext);
这给了我 "Rows" 的列表。每行都有一个键,每个键都是一个包含日期、Url 和数字的数组。
我可以遍历 "rows" 并自行创建对象,但这对我来说听起来不是很高效。此外,JSON 会很大,大约 5MB。
我想要的结构是这样的:
public class Click
{
public DateTime Date { get; set; }
public string Code { get; set; }
public string Url { get; set; }
public int Count { get; set; }
}
如何提取 "key" 数组并将其映射到单独的属性中。这样,我就不需要 for 循环了。
有什么想法吗?
给你。
public class Row
{
// Serialize/Deserialize the `key` into it's values.
public List<string> key { get { return new List<string>() { Date.ToString("yyyy-MM-dd"), Code, Url }; } set { Date = DateTime.Parse(value[0]); Code = value[1]; Url = value[2]; } }
// Serialize/Deserialize the `value` into `Count`.
public int value { get { return Count; } set { Count = value; } }
[ScriptIgnore]
public DateTime Date { get; set; }
[ScriptIgnore]
public string Code { get; set; }
[ScriptIgnore]
public string Url { get; set; }
[ScriptIgnore]
public int Count { get; set; }
public override string ToString()
{
return Date.ToString("yyyy-MM-dd") + ", " + Code + ", " + Url + ", " + Count;
}
}
public class RootObject
{
public List<Row> rows { get; set; }
}
public static void _Main(string[] args)
{
string json = "{\"rows\":[" +
"{\"key\":[\"2015-04-01\",\"524\",\"http://www.sampleurl.com/\"],\"value\":1}," +
"{\"key\":[\"2015-04-01\",\"524\",\"http://www.sampleurl2.com/\"],\"value\":2}," +
"{\"key\":[\"2015-04-01\",\"524\",\"http://www.sampleurl3.com\"],\"value\":1}" +
"]}";
var jss = new JavaScriptSerializer();
var example = jss.Deserialize<RootObject>(json);
foreach (Row r in example.rows)
{
Console.WriteLine(r.ToString());
}
}
它应该是不言自明的。如果您想让我详细说明,请询问。不过,这确实需要元素始终保持一致的顺序。
上面的输出:
2015-04-01, 524, http://www.sampleurl.com/, 1
2015-04-01, 524, http://www.sampleurl2.com/, 2
2015-04-01, 524, http://www.sampleurl3.com, 1
这种方法的明显好处是它的开销很低。它也很容易维护。这也意味着您显然可以在具有 ScriptIgnoreAttribute
的属性上提供 XmlIgnoreAttribute
,并且它还会生成并读取有效的序列化 XML.
注:我用的是System.Web.Script.Serialization.JavaScriptSerializer
。如果 JSON.NET
不使用 ScriptIgnoreAttribute
,则您必须应用它使用的任何属性。 (我从来没有用过JSON.NET
。)
另一个注意事项:我是针对 C#6.0
和 .NET 4.6
写的。您的结果可能会有所不同。
您可以为此创建自定义 JsonConverter
:
[JsonConverter(typeof(ClickConverter))]
public class Click
{
public DateTime Date { get; set; }
public string Code { get; set; }
public string Url { get; set; }
public int Count { get; set; }
}
public class ClickConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(Click).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var token = JToken.Load(reader);
if (token == null || token.Type == JTokenType.Null)
return null;
var click = (existingValue as Click ?? new Click());
var key = token["key"] as JArray;
if (key != null && key.Count > 0)
click.Date = (DateTime)key[0];
if (key != null && key.Count > 1)
click.Code = (string)key[1];
if (key != null && key.Count > 2)
click.Url = (string)key[2];
var value = token["value"];
if (value != null)
click.Count = (int)value;
return click;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
// Fill in with the opposite of the code above, if needed
var click = value as Click;
if (click == null)
writer.WriteNull();
else
serializer.Serialize(writer,
new
{
// Update the date string format as appropriate
// https://msdn.microsoft.com/en-us/library/8kb3ddd4%28v=vs.110%29.aspx
key = new string[] { click.Date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture), click.Code.ToString(CultureInfo.InvariantCulture), click.Url },
value = click.Count
});
}
}
public class RootObject
{
public List<Click> rows { get; set; }
}
将转换器直接应用于 class,您可以像往常一样(反)序列化:
var jsontext = @"{""rows"":[
{""key"":[""2015-04-01"",""524"",""http://www.sampleurl.com/""],""value"":1},
{""key"":[""2015-04-01"",""524"",""http://www.sampleurl2.com/""],""value"":2},
{""key"":[""2015-04-01"",""524"",""http://www.sampleurl3.com""],""value"":1}
]}";
var rows = JsonConvert.DeserializeObject<RootObject>(jsontext);
Debug.WriteLine(JsonConvert.SerializeObject(rows, Formatting.Indented));