在原来解析json数据是,一般都是用反序列化来实现json数据的解读,这需要首先知道json数据的结构并且建立相应的类才能反序列化,一旦遇到动态的json数据,这种方法就不使用。 为了解决动态解析json数据,微软有个Newtonsoft.Json封装类十分好用,里面的JToken直接实现对JSON的增删改查。
JToken的层次结构是这样的:
JToken -抽象基类
JContainer - 能够包含其它JToken的JToken抽象基类
JArray - 表示一个JSON数组(包含一个有序的List)
JObeject - 表示一个JSON对象(包含一个IEnumerable)
JProperty - 表示一个JSON属性(在JObject中是一个name/JToken键值对)
JValue - 表示一个原生JSON值(string,number,boolean,null)
增删改查:
var cardJson = "['身份证','银行卡','门禁卡']";
var cardJArray = JArray.Parse(cardJson);
var p = new Person { Name="fan",Age=12,Dog=new Dog { Name="奶牛"} };
JObject jobj= JObject.FromObject(p);
//添加属性
jobj["NickName"] = "fan";
jobj["Wifes"] = new JArray("rose", "lisa");
((JArray)jobj["Wifes"]).Add( "july");
jobj["Cards"] = cardJArray;
//修改属性
jobj["Name"] = "li";
jobj["Age"] = 9;
jobj["Dog"]["Name"] = "阿黄";
((JArray)jobj["Wifes"])[0] = "roses";
//插入属性
jobj.Property("Name").AddBeforeSelf(new JProperty("ID", 1));
//删除属性
jobj.Property("Age").Remove();
((JArray)jobj["Wifes"])[2].Remove();
//查找
//遍历属性
var props = jobj.Children().Values();
foreach (var prop in props)
{
if (!(prop is JObject) && !(prop is JArray))
{
Console.WriteLine(prop.ToString());
}
}
//遍历数组
var cardList = ((JArray)jobj["Cards"]);
foreach (var card in cardList)
{
Console.WriteLine(card.ToString());
}
//强类型读取
Console.WriteLine(jobj.Value<int>("ID"));
var p2 = jobj.ToString();
使用集合初始化语法:
JObject o = new JObject
{
{"CPU","Intel"},
{"Memory",2048},
{
"Drives",new JArray
{
"DVD",
"U盘"
}
}
};
Console.WriteLine(o.ToString());
使用dynamic初始化:
dynamic address = new JObject();
address.Province = "beijing";
address.City = "beijing";
address.County = "zhongguo";
address.Villages = new JArray("aa", "bb");
Console.WriteLine(address.ToString());
使用JTokenWriter初始化:
JTokenWriter writer = new JTokenWriter();
writer.WriteStartObject();
writer.WritePropertyName("Title");
writer.WriteValue("aaaaaaa???");
writer.WritePropertyName("Detail");
writer.WriteStartArray();
writer.WriteValue("Yes");
writer.WriteValue("No");
writer.WriteValue("Unknown");
writer.WriteEndArray();
writer.WriteEndObject();
JObject o = (JObject)writer.Token;
Console.WriteLine(o.ToString());
使用.NET值初始化:
JValue i = (JValue)JToken.FromObject(123);
Console.WriteLine(i.Type);
Console.WriteLine(i.ToString());
JValue s = (JValue)JToken.FromObject("GongHui");
Console.WriteLine(s.Type);
Console.WriteLine(s.ToString());
Address address = new Address
{
City = "GuangZhou",
Province = "GuangDong",
County = "ShiQiao",
Villages = new List<string>
{
"111",
"222"
}
};
JObject o = (JObject)JToken.FromObject(address);
Console.WriteLine(o.ToString());
遍历JSON属性:
/// <summary>
/// 遍历所以节点,替换其中某个节点的值
/// </summary>
/// <param name="jobj">json数据</param>
/// <param name="nodeName">节点名</param>
/// <param name="value">新值</param>
private static void JSON_SetChildNodes(ref JToken jobj, string nodeName, string value)
{
try
{
JToken result = jobj as JToken;//转换为JToken
JToken result2 = result.DeepClone();//复制一个返回值,由于遍历的时候JToken的修改会终止遍历,因此需要复制一个新的返回json
//遍历
var reader = result.CreateReader();
while (reader.Read())
{
if (reader.Value != null)
{
if (reader.TokenType == JsonToken.String || reader.TokenType == JsonToken.Integer || reader.TokenType == JsonToken.Float)
{
Regex reg = new Regex(@"" + nodeName + "$");
//SelectToken(Path)方法可查找某路径下的节点,在Newtonsoft.Json 4.5 版本中不可使用正则匹配,在6.0版本中可用使用,会方便很多,6.0版本下替换值会更方便,这个需要特别注意的
if (reg.IsMatch(reader.Path))
{
result2.SelectToken(reader.Path).Replace(value);
}
}
}
}
jobj = result2;
}
catch (Exception ex)
{
}
}
手动创建JObject:
var json = new JObject(
new JProperty("status", result.Status.ToString()),
new JProperty("results", new JObject(result.Entries.Select(pair =>
new JProperty(pair.Key, new JObject(
new JProperty("status", pair.Value.Status.ToString()),
new JProperty("description", pair.Value.Description),
new JProperty("data", new JObject(pair.Value.Data.Select(
p => new JProperty(p.Key, p.Value))))))))));
var str = json.ToString();
JToken合并:
需要引一个Nuget包:MassTransit
添加引用:using MassTransit.Courier.Serialization;
jObj.Merge(JObject.Parse(userTranslate.ValueJSON));
JToken查找:
jObject.SelectToken($".{path}");//根据路径查找
Object转JToken:
JToken.FromObject(object)
JToken转Object:
jObj.ToObject<List<ApiOrderInfoSelectModel>>();
Merge方法:合并json
JObject o1 = JObject.Parse(@"{
'FirstName': 'John',
'LastName': 'Smith',
'Enabled': false,
'Roles': [ 'User' ]
}");
JObject o2 = JObject.Parse(@"{
'Enabled': true,
'Roles': [ 'Admin' ]
}");
o1.Merge(o2, new JsonMergeSettings
{
// union arrays together to avoid duplicates
MergeArrayHandling = MergeArrayHandling.Union
});
string json = o1.ToString();
// {
// "FirstName": "John",
// "LastName": "Smith",
// "Enabled": true,
// "Roles": [
// "User",
// "Admin"
// ]
// }