【问题标题】:JSON Deserialization in C# comparisonC#中的JSON反序列化比较
【发布时间】:2015-02-13 14:33:30
【问题描述】:

我以前从未使用过 JSON 数据。我正在尝试反序列化以下行:

{"Mails":[null,{"ID":"ulasdas@gmail.com","Status":true},{"ID":"ADSsdasA@ONO.COM","Status":false}]}

我正在使用以下代码,但它不起作用:

public Boolean checkValidLicense(string usermail)
{
    Boolean validUser = false;

    HttpWebRequest req = WebRequest.Create("https://popping-heat-1908.firebaseio.com/.json") as HttpWebRequest;
    using (HttpWebResponse resp = req.GetResponse() as HttpWebResponse)
    {

        StreamReader reader = new StreamReader(resp.GetResponseStream());
        string json = reader.ReadToEnd();

        dynamic result = Newtonsoft.Json.JsonConvert.DeserializeObject(json);

        foreach (var item in result.Mails)
        {
            if (usermail == item.ID && item.Status == "true") 
            {
                validUser = true;
                break;
             }

        }

        return validUser;
    }

我明白了:

“Newtonsoft.Json.Linq.JValue”不包含“ID”的定义。

【问题讨论】:

  • 您能否创建一个类型化模型并使用通用 (<T>) API?

标签: c# json linq


【解决方案1】:

除非你有充分的理由,否则不要反序列化为dynamic 类型。相反,创建一个要反序列化的类型。一个很好的工具是json2csharp,尽管您可能经常需要对它无法推断的事情进行微调。下面,我们做了两个类。 Mail 代表单个项目,MailCollection 是我们要反序列化的根 JSON 对象,它只包含 Mail 对象的集合。

public class Mail
{
    public string ID { get; set; }
    public bool Status { get; set; }
}

//This is the root object, it's going to hold a collection of the mail
public class MailCollection
{
    public List<Mail> Mails { get; set; }
}

//we pass a type parameter telling it what type to deserialize to
MailCollection result = Newtonsoft.Json.JsonConvert.DeserializeObject<MailCollection>(json);
foreach (var item in result.Mails)
{
    if (usermail == item.ID && item.Status) //since item.Status is a bool, don't compare to a string.
    {
        validUser = true;
        break;
    }
}

【讨论】:

  • 有一个非常有用的工具,很少有人知道它直接包含在 Visual Studio 本身中!复制剪贴板中的 JSON,然后转到 C# 代码文件,然后 Edit -> Paste special -> Paste JSON as classes。大多数情况下工作得很好,并且可以对 XML 做同样的事情,为序列化添加属性等等。
  • @Gimly 我现在没有启动 VS。这需要什么版本,是否需要任何特殊工具,例如 Mads Kristensen 的 Web Extensions?
  • 不确定是哪个版本开始的,但至少它在 2012 年以后出现。而且它是内置的,无需特殊工具,直接在裸VS中。
【解决方案2】:

问题是您得到的响应的第一个值是null。这是您从请求中得到的结果:

{
  "Mails": [
    null,
    {
      "ID": "ulrickpspg@gmail.com",
      "Status": true
    },
    {
      "ID": "ADSA@ONO.COM",
      "Status": false
    }
  ]
}

所以换行:

if (usermail == item.ID && item.Status == "true") 

到行:

if (item.Value != null && usermail == item.ID && item.Status == "true")

【讨论】:

  • 这如何解决 OP 的问题?你只是在复制他已经发布的回复。
  • 你知道如何去掉开头的空元素吗?
  • 是一次性的还是你所有的 json 都是这种格式? @Aldridge1991
【解决方案3】:
  1. 您需要表示一个对象以供 JSON 理解。

用途

    using System.IO;
    using Newtonsoft.Json;

对象

    [JsonObject]
    public class MailItem
    {
        public int ID { get; set; }
        public Boolean Status { get; set; }

        [JsonIgnore]
        public String SomethingToNotInclude { get; set; }
    }

获取

  1. 构建一个 json 类来与创建、添加、编辑和删除进行交互。首先我们需要将json反序列化为List&lt;MailItems&gt;

    private String path = "pathTo.json";
    public List<MailItem> GetMailItems()
    {
        if (!File.Exists(path))
            File.WriteAllText(path, "[]"); //returns an empty list
    
        String json = File.ReadAllText(path);
        return JsonConvert.DeserializeObject<List<MailItem>>(json);
    }
    

添加

  1. 序列化的时候,我得到一个完整的json列表,然后将对象MailItems添加到List中,然后将列表序列化为json,最后将json写入文件。

    public void AddMailItem(MailItem mailItem)
    {
        String json = File.ReadAllText(fullPath);
        List<MailItem> mailItemList = JsonConvert.DeserializeObject<List<MailItem>>(json);
            if (mailItemList == null)
                mailItemList = new List<MailItem>();
        mailItemList.Add(mailItem);
        String json = JsonConvert.SerializeObject(mailItemList, Formatting.Indented);
        File.WriteAllText(json);
    }
    

编辑

  1. 更新现有项目时:

    public void EditMailItem(MailItem mailItem)
    {
        String jsonRead = File.ReadAllText(fullPath);
        List<MailItem> mailItemList = JsonConvert.DeserializeObject<List<MailItem>>(jsonRead);
        int indexOfMailItem = mailItemList.FindIndex(o => o.ID == mailItem.ID); //LINQ
        mailItemList[indexOfMailItem] = mailItem;
        String jsonWrite = JsonConvert.SerializeObject(mailItemList, Formatting.Indented);
        File.WriteAllText(jsonWrite);
    }
    

【讨论】:

  • List&lt;Mails&gt; mailsList = JsonConvert.DeserializeObject&lt;List&lt;Log&gt;&gt;(json); Log 是什么?为什么Mails 只代表一个Mail 对象时是复数?为什么要将 JSON 对象反序列化为 C# 集合?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-06
  • 1970-01-01
  • 2012-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多