如何使用JSON序列化对象列表

时间:2019-05-12 13:00:08

标签: c# .net json

我正在开发一种软​​件来管理我的硬币收集。我需要在JSON文件中导出对象列表的内容,但是每次我想显示数据库中实际存在的硬币时,都会遇到此错误:

在完成读取JSON内容后遇到的其他文本:[。路径”,第1行,位置109。

这是应该发生的所有地方:

List<Coin> coins = new List<Coin>();

public bool AddACoin (int ID, String coinName, String coinNation, String coinStatus, int coinYear, int quantity, float value)
{
    var jsonSerializer = new JsonSerializer();

    using (StreamWriter streamWriter = new StreamWriter(path, true))
    using (JsonWriter jsonWriter = new JsonTextWriter(streamWriter))
    {
        coins.Add(new Coin(ID, coinName, coinNation, coinStatus, coinYear, quantity, value));
        jsonSerializer.Serialize(jsonWriter, coins.ToList());
    }

    return true;
}

输出存储在方括号的不同块中。对于插入的每个对象,我都有一个障碍。相反,我应该将每个对象放在一个独特的方括号内。预先感谢。

编辑:这是JSON文件的内容

[{"ID":0,"coinName":"1 Euro","coinNation":"Ita","coinStatus":"FdC","coinYear":2005,"quantity":1,"value":4.7}][{"ID":0,"coinName":"1 Euro","coinNation":"Ita","coinStatus":"FdC","coinYear":2005,"quantity":1,"value":4.7},{"ID":1,"coinName":"2 Euro","coinNation":"Bel","coinStatus":"FdC","coinYear":2004,"quantity":1,"value":30.0}]

正如我所说,所有内容都应放在方括号的唯一块内。

3 个答案:

答案 0 :(得分:1)

我认为我刚刚找到了解决问题的方法,并将与您分享。我已经更改了一些行,现在有:

public bool AddACoin (int ID, String coinName, String coinNation, String coinStatus, int coinYear, int quantity, float value)
    {
        var jsonSerializer = new JsonSerializer();

        using (StreamReader streamReader = new StreamReader(path, true))
        {
            string json = streamReader.ReadToEnd();
            coins = JsonConvert.DeserializeObject<List<Coin>>(json);
            coins.Add(new Coin(ID, coinName, coinNation, coinStatus, coinYear, quantity, value));
            string newJson = JsonConvert.SerializeObject(coins);
            streamReader.Close();
            File.WriteAllText(path, newJson);
        }
            return true;
    }

如果我的想法正确,执行此操作将使程序读取直到到达EOF,然后在序列化/反序列化列表之后追加新对象。目前,这似乎很好。

答案 1 :(得分:0)

我建议您使用NewtonsoftJSON(可以通过NuGet进行安装),每次添加新硬币时都要清除json文件,其中有硬币管理器示例供您使用:

public class CoinsManager
{
    public List<Coin> Coins { get; set; }

    public string FilePath { get; set; }

    public CoinsManager(string filePath)
    {
        FilePath = filePath;
        Coins = new List<Coin>();
    }

    public void LoadCoins()
    {
        if (File.Exists(FilePath))
        {
            //If file exists, but empty, save empty settings to it
            if (new FileInfo(FilePath).Length == 0)
            {
                SaveSettings();
            }
            else
            {
                //Read json from file
                using (StreamReader r = new StreamReader(FilePath))
                {
                    string json = r.ReadToEnd();
                    //Convert json to list
                    Coins = JsonConvert.DeserializeObject<List<Coin>>(json);
                }
            }
        }
        else
        {
            //Create file
            File.Create(FilePath).Close();

            //Wait for filesystem to create file
            while (!File.Exists(FilePath))
            {
                System.Threading.Thread.Sleep(100);
            }

            //Save empty settings to file
            SaveSettings();
        }
    }

    public void SaveSettings()
    {
        string json = JsonConvert.SerializeObject(Coins);

        File.WriteAllText(FilePath, json);
    }

    //Can save or update passed coin
    public void SaveCoin(Coin coin)
    {
        //Select old coin
        var oldCoin = Coins.Where(c => c.ID == coin.ID).FirstOrDefault();

        //If there was no old coin, get last existing coin id, or zero if Coins list is empty
        if (oldCoin == null)
        {
            int lastId;
            if (Coins.Count != 0)
                lastId = Coins.Count - 1;
            else
                lastId = 0;

            coin.ID = lastId + 1;
            Coins.Add(coin);
        }
        else
        {
            int index = Coins.IndexOf(oldCoin);
            Coins[index] = coin;
        }
    }

    public void DeleteCoin(Coin coin)
    {
        Coins.RemoveAll(c => c.ID == coin.Id);
    }
}

及其用法:

    CoinsManager coinsManager = new CoinsManager("coinsStorage.json");
    coinsManager.LoadCoins();
    coinsManager.SaveCoin(new Coin {
    ...
    });
    coinsManager.SaveSettings();

答案 2 :(得分:0)

如果我理解正确,则只需更改此行:

StreamWriter streamWriter = new StreamWriter(path, true);

对此:

StreamWriter streamWriter = new StreamWriter(path, false);

您的问题是,您总是将带有所有列表的new json添加到文件中,而不仅仅是编写列表。

因为使用所需的文件,并且您想要附加的唯一选择是读取文件,然后添加元素并再次写入。

您可以在应用程序启动时阅读它,并且可以对它进行管理,因为您的列表似乎是全局的。

或者您可以在要写入文件之前立即阅读它。

在任何一种情况下,您都需要添加我编写的修复程序。

您可以使用它来读取列表中的json:

string myJsonString = File.ReadAllText(path);
coins = JsonConvert.DeserializeObject<List<Coin>>(myJsonString);

这是完整功能:

public bool AddACoin (int ID, String coinName, String coinNation, String coinStatus, int coinYear, int quantity, float value)
{
    var jsonSerializer = new JsonSerializer();

    using (StreamWriter streamWriter = new StreamWriter(path, false))
    using (JsonWriter jsonWriter = new JsonTextWriter(streamWriter))
    {
        string myJsonString = File.ReadAllText(path);
        coins = JsonConvert.DeserializeObject<List<Coin>>(myJsonString);
        coins.Add(new Coin(ID, coinName, coinNation, coinStatus, coinYear, quantity, value));
        jsonSerializer.Serialize(jsonWriter, coins.ToList());
    }

    return true;
}