如果 JSON 数据没有从 newtonsoft json 很好地解析,我该如何解析它。请参考我下面的代码:
var web_uri = new Uri("www.example.com");
var resp = await client2.GetAsync(web_uri);
var resp_to_str = await resp.Content.ReadAsStringAsync();
var json_obj = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(resp_to_str);
最后,我解析了 JSON。 现在,它按预期生成。
{
"Sex": "Male",
"category": "A",
"ID": 14,
"created": "2016-03-03",
"Tag": "2340",
"members": [{
"type": "A",
"name": "fam_mem",
"state": "ca",
"Family": {
"myGuardName": "tony",
"details": [{
"address": "ca",
"type": "A"
}]
}
}]
}
**RootObject omyclass = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(json_obj);**
现在我在上面一行出现错误:System.Linq.Expressions 中发生了类型为"Microsoft.CSharp.RuntimeBinder.RuntimeBinderException"的异常.dll但未在用户代码中处理
其他信息:'Newtonsoft.Json.JsonConvert.DeserializeObject(string)' 的最佳重载方法匹配有一些无效参数
public class Detail
{
public string address { get; set; }
public string type { get; set; }
}
public class Family
{
public string myGuardName { get; set; }
public List<Detail> details { get; set; }
}
public class Member
{
public string type { get; set; }
public string name { get; set; }
public string state { get; set; }
public Family Family { get; set; }
}
public class RootObject
{
public string Sex { get; set; }
public string category { get; set; }
public int ID { get; set; }
public string created { get; set; }
public string Tag { get; set; }
public List<Member> members { get; set; }
}
TextBlock.Text = omyclass
我已经更新了问题
希望对您有所帮助:
var web_uri = new Uri("www.example.com");
var resp = await client2.GetAsync(web_uri);
var resp_to_str = await resp.Content.ReadAsStringAsync();
RootObject omyclass = JsonConvert.DeserializeObject<RootObject>(resp_to_str); //pass the response string here.
根据OP的评论更新:
textBlock2.Text = omyclass + "----!";
不起作用,因为 omyclass 是RootObject
,而不是string
您必须获取所需的信息并将其附加到textBlock2
:
textBlock2.text = omyclass.Sex + "----!";
更新 2(OP 获取字符串作为键值对):
用法:textBlock2.text = omyclass + "----!";
覆盖RootObject.ToString()
并使用Reflection
获取属性和属性值
public class RootObject
{
public string Sex { get; set; }
public string category { get; set; }
public int ID { get; set; }
public string created { get; set; }
public string Tag { get; set; }
public List<Member> members { get; set; }
public override string ToString()
{
var values = new List<string>();
foreach (var property in GetType().GetProperties())
{
values.Add(property.Name + ": " + property.GetValue(this));
}
return string.Join(", ", values);
}
}
问题是JsonConvert.DeserializeObject<T>(string)
期望一个字符串作为输入参数 - 但你没有传入字符串。 您正在传入json_obj
这是上一次反序列化调用返回的dynamic
:
var json_obj = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(resp_to_str);
var omyclass = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(json_obj);
JsonConvert
从第一个dynamic
调用返回的内容实际上是一个包含 LINQ 到 JSON 令牌树的JToken
,而不是字符串。 这会导致在进行第二次调用时出现RuntimeBinderException
。
无需以这种方式对 JSON 字符串进行双重反序列化。 只需将resp_to_str
传递给JsonConvert.DeserializeObject<RootObject>()
:
var omyclass = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(resp_to_str);
原型小提琴。
更新
如果要在文本框中查看反序列化类的所有字段和属性,可以将其重新序列化为 JSON:
var reserializedJson = JsonConvert.SerializeObject(omyclass, Formatting.Indented);
textBlock2.Text = reserializedJson;
如果你这样做
textBlock2.Text = omyclass + "----!"
您只是显示类的ToString()
值。 由于您没有覆盖此方法,因此它只会显示类名。
如果不想重新序列化,可以使用以下扩展方法:
public static class ObjectExtensions
{
public static StringBuilder ToStringWithReflection<T>(this T obj, StringBuilder sb)
{
sb = sb ?? new StringBuilder();
if (obj == null)
return sb;
if (obj is IEnumerable)
{
sb.Append("[");
var first = true;
foreach (var item in ((IEnumerable)obj))
{
if (!first)
sb.Append(",");
sb.Append(item == null ? "" : item.ToString());
first = false;
}
sb.Append("]");
}
else
{
var type = obj.GetType();
var fields = type.GetFields();
var properties = type.GetProperties().Where(p => p.GetIndexParameters().Length == 0 && p.GetGetMethod(true) != null && p.CanRead);
var query = fields
.Select(f => new KeyValuePair<string, object>(f.Name, f.GetValue(obj)))
.Concat(properties
.Select(p => new KeyValuePair<string, object>(p.Name, p.GetValue(obj, null))));
sb.Append("{").Append(obj.GetType().Name).Append(": ");
var first = true;
foreach (var pair in query)
{
if (!first)
sb.Append(", ");
sb.Append(pair.Key).Append(": ");
if (pair.Value is IEnumerable && !(pair.Value is string))
pair.Value.ToStringWithReflection(sb);
else
sb.Append(pair.Value == null ? "null" : pair.Value.ToString());
first = false;
}
sb.Append("}");
}
return sb;
}
public static string ToStringWithReflection<T>(this T obj)
{
return obj.ToStringWithReflection(new StringBuilder()).ToString();
}
}
然后做
textBlock2.Text = omyclass.ToStringWithReflection() + "----!"
更新 2
或者,如果要递归包含对象层次结构中的属性,则可以重写每个属性的 ToString()
方法,如下所示:
public class Detail
{
public string address { get; set; }
public string type { get; set; }
public override string ToString() { return this.ToStringWithReflection(); }
}
public class Family
{
public string myGuardName { get; set; }
public List<Detail> details { get; set; }
public override string ToString() { return this.ToStringWithReflection(); }
}
public class Member
{
public string type { get; set; }
public string name { get; set; }
public string state { get; set; }
public Family Family { get; set; }
public override string ToString() { return this.ToStringWithReflection(); }
}
public class RootObject
{
public string Sex { get; set; }
public string category { get; set; }
public int ID { get; set; }
public string created { get; set; }
public string Tag { get; set; }
public List<Member> members { get; set; }
public override string ToString() { return this.ToStringWithReflection(); }
}
然后ToString()
输出将是:
{RootObject: Sex: Male, category: A, ID: 14, created: 2016-03-03, Tag: 2340, members: [{Member: type: A, name: fam_mem, state: ca, Family: {Family: myGuardName: tony, details: [{Detail: address: ca, type: A}]}}]}
自定义 JSON 格式化程序并按照您想要的方式解析它。它可以在框架级别实现,以便根据您的要求解析所有数据。从 MediaType格式化程序继承自定义格式化程序。
实现 MediaTypeFormatter.Pasre 的虚拟和抽象函数,根据您的要求在此处访问数据。
我已经以这种方式实现了格式化程序,它甚至解析了复杂的数据以匹配我想要的数据。
序列化复杂 Json 时,如果未正确反序列化,则值变为 null。要反序列化复杂的 Json,请使用 JsonMediaTypeFormatter。
我的例子
在您的配置文件中添加
config.Formatters.Clear();
config.Formatters.Insert(0, new JsonNetFormatterDecide()); // My custom formatter
config.Formatters.Insert(1, new JsonMediaTypeFormatter());//Default Formatter
config.MapHttpAttributeRoutes();`
所以我使用我的自定义格式化程序进行所有获取操作。根据需要格式化数据并发送到客户端。我面临的问题是在接受复杂的Json数据(例如Jsonobjects中的Jsonarrays)时。所以在我的配置文件中,我在 Config.formatters 的索引 1 中添加了 JsonMediaTypeFormatter()。
在我的自定义格式化程序中
public override bool CanReadType(Type type)
{
return false;
}
这使得JsonMediaType格式化程序是一个非常流行的格式化程序,用于反序列化复杂数据以进行反序列化。
底线是您可以使用JsonMediaTypeFormatter
来反序列化复杂的 Json 数据
它有一些预定义的函数来反序列化。
通过查看您的 Json,似乎 Json 对象中的 Json 数组是您的 Json 无法正确反序列化的原因
如果你打算编写你的自定义 Json 格式化程序,你可以在框架级别实现,比如
public class JsonNetFormatterDecide : MediaTypeFormatter
{
//......
public override bool CanReadType(Type type)
{
return false; //this causes the // project to use the second formatter in the config file ie,JsonMediaTypeFormatter or the //default Json Formatter
}
}