如果没有很好地解析JSON语法,请解析它

时间:2016-03-03 03:26:59

标签: c# json json.net win-universal-app

如果从newtonsoft json中解析不好,我如何解析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);** 

现在我在上面的行中收到错误: 类型&#39; Microsoft.CSharp.RuntimeBinder.RuntimeBinderException&#39;的例外情况发生在System.Linq.Expressions.dll中但未在用户代码中处理

附加信息:最佳重载方法匹配&#39; Newtonsoft.Json.JsonConvert.DeserializeObject(string)&#39;有一些无效的论点

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

我更新了问题

4 个答案:

答案 0 :(得分:1)

问题是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实际上是一个JToken,其中包含LINQ-to-JSON个令牌树,而不是一个字符串。这会导致RuntimeBinderException进行第二次呼叫。

无需以这种方式对JSON字符串进行双重反序列化。只需将resp_to_str传递给JsonConvert.DeserializeObject<RootObject>()

即可
var omyclass = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(resp_to_str);

原型fiddle

<强>更新

如果要在文本框中查看反序列化类的所有字段和属性,可以将其重新序列化为JSON:

var reserializedJson = JsonConvert.SerializeObject(omyclass, Formatting.Indented);
textBlock2.Text = reserializedJson;

如果你这样做

textBlock2.Text = omyclass + "----!"

您只是显示班级的ToString()值。由于你没有overridden this method,它只会显示班级名称。

如果您不想重新序列化,可以使用以下扩展方法:

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}]}}]}

答案 1 :(得分:1)

希望有所帮助:

textBlock2.Text = omyclass + "----!";

来自OP的评论:

RootObject无效,因为omyclass为string,而不是textBlock2

您必须获取所需信息并将其附加到textBlock2.text = omyclass.Sex + "----!";

textBlock2.text = omyclass + "----!";

UPDATE 2(OP获取字符串作为键值对):

用法: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); } } 获取属性&amp;财产价值

for(int i=-; i< list.size(); i++){
     build list.getAt(i)
}

答案 2 :(得分:0)

您可以使用自定义Json格式化程序并按照您希望的方式进行解析。它可以在框架级别实施,以便根据您的要求解析所有数据。从 MediaTypeFormatter 继承自定义格式化程序。

在此处根据您的要求实现MediaTypeFormatter.Pasre数据的虚拟和抽象功能。

我已经以这种方式实现了格式化程序,甚至可以解析复杂数据以匹配我想要的数据。

答案 3 :(得分:0)

如果序列化复杂的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();`

所以我使用自定义格式化程序进行所有get操作。格式化我想要的数据并发送给客户端。我遇到的问题是接受复杂的Json数据(例如Jsonobjects中的Jsonarrays)。所以在我的配置文件中,我在Config.formatters的索引1中添加了JsonMediaTypeFormatter()。

在我的自定义格式化程序

public override bool CanReadType(Type type)
{
    return false;
}

这使得JsonMediaTypeFormatter成为一种非常流行的格式化程序来反序列化复杂数据以进行反序列化。

底线是您可以使用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
    }
}