如何将JSON文件反序列化为List <t> c#

时间:2017-05-04 03:54:42

标签: c# json winforms deserialization

我无法反序列化包含多个Account类型对象的JSON文件。以下是我构建data.json文件的方法。我有一个帐户列表List<Account>,它像往常一样序列化。我通过添加一个新行来分隔json文件中的每个对象。

List<Account> listOfAccounts = new List<Account>();
if (listOfAccounts != null)
{
    foreach (var item in listOfAccounts)
    {
        JavaScriptSerializer ser = new JavaScriptSerializer();
        string outputJSON = ser.Serialize(item);
        // I added Environmetn.NewLine to separate each account in json file.
        File.AppendAllText("data.json", outputJSON + Environment.NewLine);
    }
}

现在,当我尝试将所有帐户从JSON文件检索到List<Account>时,我收到错误消息:System.ArgumentException: 'Invalid JSON primitive:
请帮助找到solutin,这样我就可以从JSON文件中获取所有对象。

private void JsonFileLoad()
{
    if(File.Exists("data.json"))
    {
        String JSONtxt = File.ReadAllText("data.json");
        JavaScriptSerializer ser = new JavaScriptSerializer();
        // Not sure how to deserialize all lines into List<account>
        List<Account> desirializedAccounts = ser.Deserialize<List<Account>>(JSONtxt);                      
    }
} 

我非常感谢您提供的任何帮助。

2 个答案:

答案 0 :(得分:2)

首先,您应该使用标准的json格式进行序列化。你正在做的是序列化对象和写入文件。应该是,将列表完全序列化为json格式。 但假设您可能有特定的原因,我在不同的场景中给出了许多可能的解决方案。

注意:我使用了Newtonsoft.Json,因为这很快,我觉得很容易。 http://www.newtonsoft.com/json

https://www.nuget.org/packages/newtonsoft.json/

解决方案:

//Class for testing object
public class Account
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

解决方案1:推荐

/// <summary>
/// Serializing the list in single go
/// </summary>
public void Serialize()
{
    List<Account> listOfAccounts = new List<Account>();
    listOfAccounts.Add(new Account { Id = 1, Name = "First" });
    listOfAccounts.Add(new Account { Id = 2, Name = "Second" });
    listOfAccounts.Add(new Account { Id = 3, Name = "Third" });

    string outputJSON = Newtonsoft.Json.JsonConvert.SerializeObject(listOfAccounts, Newtonsoft.Json.Formatting.Indented);
    File.WriteAllText(@"c:\temp\data.json", outputJSON + Environment.NewLine);
}

/// <summary>
/// Serializing the list, one by one object
/// Comma is appended to every object in json format
/// Finally, enclosed it with [ and ] to make it array of objects
/// </summary>
public void Serialize2()
{
    List<Account> listOfAccounts = new List<Account>();
    listOfAccounts.Add(new Account { Id = 1, Name = "First" });
    listOfAccounts.Add(new Account { Id = 2, Name = "Second" });
    listOfAccounts.Add(new Account { Id = 3, Name = "Third" });
    string outputJSON = "";
    foreach(var item in listOfAccounts)
    {
        outputJSON += Newtonsoft.Json.JsonConvert.SerializeObject(item, Newtonsoft.Json.Formatting.Indented)+",";
    }

    File.WriteAllText(@"c:\temp\data.json", "["+outputJSON + "]");
}

/// <summary>
/// Read serialized data into list of objects
/// </summary>
public void DeSerialize()
{
    if (File.Exists(@"c:\temp\data.json"))
    {
        String JSONtxt = File.ReadAllText(@"c:\temp\data.json");
        var accounts = Newtonsoft.Json.JsonConvert.DeserializeObject<IEnumerable<Account>>(JSONtxt);
    }
}

解决方案2:根据您的要求

/// <summary>
/// Non standard json serialization (object one by one) Highly discouraged unless you have specific reason
/// Assuming the output will not have internal objects 
/// </summary>
public void SerializeNonStandard()
{
    List<Account> listOfAccounts = new List<Account>();
    listOfAccounts.Add(new Account { Id = 1, Name = "First" });
    listOfAccounts.Add(new Account { Id = 2, Name = "Second" });
    listOfAccounts.Add(new Account { Id = 3, Name = "Third" });

    foreach (var item in listOfAccounts)
    {
        string outputJSON = Newtonsoft.Json.JsonConvert.SerializeObject(item, Newtonsoft.Json.Formatting.Indented);
        File.AppendAllText(@"c:\temp\data-ns.json", outputJSON + Environment.NewLine);
    }
}
/// <summary>
/// Deserializes the list in one by one fashion and appends to list
/// </summary>
public void DeSerializeNonStandard()
{
    if (File.Exists(@"c:\temp\data-ns.json"))
    {
        List<Account> listOfAccounts = new List<Account>();
        String JSONtxt = File.ReadAllText(@"c:\temp\data-ns.json");

        //Capture JSON string for each object, including curly brackets 
        Regex regex = new Regex(@".*(?<=\{)[^}]*(?=\}).*", RegexOptions.IgnoreCase);
        MatchCollection matches = regex.Matches(JSONtxt);
        foreach(Match match in matches)
        {
            string objStr = match.ToString();
            Account account = Newtonsoft.Json.JsonConvert.DeserializeObject<Account>(objStr);
            listOfAccounts.Add(account);
        }
    }
}

/// <summary>
/// Deserializes the non standard json to list of accounts
/// Splits the object strings, merges with comma and encloses with [] to make it array of objects format and deserializes
/// </summary>
public void DeSerializeNonStandardList()
{
    if (File.Exists(@"c:\temp\data-ns.json"))
    {
        String JSONtxt = File.ReadAllText(@"c:\temp\data-ns.json");

        //Capture JSON string for each object, including curly brackets 
        Regex regex = new Regex(@".*(?<=\{)[^}]*(?=\}).*", RegexOptions.IgnoreCase);
        MatchCollection matches = regex.Matches(JSONtxt);

        string joinedJSON = string.Join(",", matches.Cast<Match>().Select(m => m.Value));
        joinedJSON = string.Format("[{0}]", joinedJSON);

        var listOfAccounts = Newtonsoft.Json.JsonConvert.DeserializeObject<IEnumerable<Account>>(joinedJSON);

    }
}

答案 1 :(得分:1)

您正在序列化帐户而不是帐户列表,这就是为什么反序列化失败的原因。你需要在新的行中分开这些帐户吗?如果是这样你可以尝试添加char&#39; [&#39;在第一个和最后一个char&#39;]&#39;在data.json。