3

I am having trouble reading and writing multiple records from and to the json file. Before I added the "Items" array and added a second record it loaded the file fine. My problem is I am trying to load multiple items for the players inventory. When I try to do this it loads only the one item and says 'Additional text encountered after finished reading JSON content:' and it points to the line number in the json file which is ending the first item. Also when trying to save using a for loop it gives me an error saying that the property name already exists, so I tried making the whole thing an array but this didn't work either. I would also like to point out that this version of Json is different than some other versions I have seen so it is difficult to find information on this. I am using the Json from the Unity asset store. Any help would be appreciated.

{
  "Items":
   [
    {
      "Id": 0,
      "Title": "Test0",
      "Value": 15,
      "Description": "TESTing0",
      "Stackable": true,
      "Rarity": 1,
      "Slug": "TEST0",
      "Stats": 
     [ 
           {
            "Power": 9,
            "Defense" : 7,
            "Vitality": 3
           }
     ],

     "Id": 1,
      "Title": "Test1",
      "Value": 16,
      "Description": "TESTing1",
      "Stackable": false,
      "Rarity": 1,
      "Slug": "TEST1",
      "Stats": 
      [
            {
            "Power": 9,
            "Defense" : 7,
            "Vitality": 3
            }
      ]
    }
  ]
}

Here is my code so far. My save and load functions are completely different because I have been trying different things to get this working the way I intended. Right now my Load function is trying to load the array of "Items": Which is actually multiple records. For some reason this is not working for me and I get an error message saying "Accessed JObject values with invalid key value: 0. Object property name expected." I have also tried this without the array "Items": but then it reads one record and says 'Additional text encountered after finished reading JSON content:'

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.IO;

public class PlayerDatabase : MonoBehaviour
{
    private List<Item> database = new List<Item>();

    public class Item
    {
        public int Id { set; get; }
        public string Title { set; get; }
        public int Value { set; get; }
        public int Power { set; get; }
        public int Defense { set; get; }
        public int Vitality { set; get; }
        public string Description { set; get; }
        public bool Stackable { set; get; }
        public int Rarity { set; get; }
        public string Slug { set; get; }

        public Item(int id, string title, int value, int power, int defense, int vitality, string description, bool stackable, int rarity, string slug)
        {
            this.Id = id;
            this.Title = title;
            this.Value = value;
            this.Power = power;
            this.Defense = defense;
            this.Vitality = vitality;
            this.Description = description;
            this.Stackable = stackable;
            this.Rarity = rarity;
            this.Slug = slug;
        }
    }

    void Save()
    {
        JObject playerJson = new JObject();

        for (int i = 0; i < 1; i++)
        {
            playerJson.Add("Id", i);
            playerJson.Add("Title", Title);
            playerJson.Add("Value", Value);
            playerJson.Add("Description", Description);
            playerJson.Add("Stackable", Stackable);
            playerJson.Add("Rarity", Rarity);
            playerJson.Add("Slug", Slug);

            JArray jaStats = new JArray();
            jaStats.Add(Power);
            jaStats.Add(Defense);
            jaStats.Add(Vitality);
            playerJson.Add("Stats", jaStats);

            string path = Application.dataPath + "/Inventory System/StreamingAssets/Player.Json";
            File.WriteAllText(path, playerJson.ToString());
        }   
    }


    void Load()
    {
        string path = Application.dataPath + "/Inventory System/StreamingAssets/Player.Json";
        string jsonString = File.ReadAllText(path);
        JObject itemJson = JObject.Parse(jsonString);

        //Load values
        for (int i = 0; i < itemJson.Count; i++)
        {

            database.Add(new Item((int)itemJson[i]["Items"]["Id"], (string)itemJson[i]["Items"]["Title"], (int)itemJson[i]["Items"]["Value"],
            (int)itemJson[i]["Items"]["Stats"]["Power"], (int)itemJson[i]["Items"]["Stats"]["Defense"], (int)itemJson[i]["Items"]["Stats"]["Vitality"],
            (string)itemJson[i]["Items"]["Description"], (bool)itemJson[i]["Items"]["Stackable"], (int)itemJson[i]["Items"]["Rarity"], (string)itemJson[i]["Items"]["Slug"]));
        }
        Debug.Log(database[0].Power);
    }

    // Update is called once per frame
    void Update ()
    {
        if (Input.GetKeyDown(KeyCode.S)) Save();
        if (Input.GetKeyDown(KeyCode.L)) Load();
    }
}
James Leshko
  • 173
  • 1
  • 3
  • 16
  • 'Multiple' means multiple 'item's in `items`, or multiple `items`s ? – MT-FreeHK Aug 08 '18 at 08:28
  • The list I created (database) of type Item should store multiple items in it. This is an example of one item in the json file "Id": 0, "Title": "Test0", "Value": 15, "Description": "TESTing0", "Stackable": true, "Rarity": 1, "Slug": "TEST0", "Stats": [ { "Power": 9, "Defense" : 7, "Vitality": 3 } ] – James Leshko Aug 08 '18 at 08:33
  • Your json structure confused me. One by one. First, the json you shown now is **not** `{ Items: [ {id:0,...}, {id:0,...}, ...] }`, but `{ Items: [{id:0,..., id:0,...}] }`. Is this correct? – MT-FreeHK Aug 08 '18 at 08:40
  • I was about to write an answer but figured it's better to mark as duplicate since Unity's `JsonUtility` can handle this json. Also, I have answered how to save and load json data which is exactly what you're doing. No need for me to repeat these. There are two links in the duplicate. If you still have issues, let me know – Programmer Aug 08 '18 at 14:24
  • I seem to have the beginning of this working but when it gets to the Stats array inside the Items array it says the argument is out of range. Here is my json file reformatted so you can understand it better. { "Items":[ {"Id": 1,"Title": "Test0","Value": 15,"Description": "TESTing0","Stackable": true,"Rarity": 1,"Slug": "TEST0","Stats":[{"Power": 9,"Defense" : 7,"Vitality": 3}]}, {"Id": 2,"Title": "Test1","Value": 16,"Description": "TESTing1","Stackable": false,"Rarity": 1,"Slug": "TEST1","Stats":[{"Power": 9,"Defense" : 7,"Vitality": 3}]} ] } – James Leshko Aug 08 '18 at 16:07
  • @Programmer What do you mean there are two links in the duplicate. Where do I find the links? – James Leshko Aug 08 '18 at 16:21
  • I've circled it for you. See [this](https://i.imgur.com/wJ7Kxjx.png) – Programmer Aug 08 '18 at 16:25
  • @Programmer Thank you, this JsonHelper class seems to be the trick here. I hope it still works for my array within an array json file. Items->Stats? – James Leshko Aug 08 '18 at 17:24
  • Don't worry about `JsonHelper` because your outer json is not a json array. Note that the class you want to serialize into must be outside the `PlayerDatabase` class that derives from PlayerDatabase. – Programmer Aug 08 '18 at 17:34
  • First of all, paste your json from your question [here](http://json2csharp.com/) to generate the proper classes. Remove all the `{ get; set; }` from the generated classes. Add `[Serializable]` to the top each generated class. The generated classes should have a class named `RootObject`. You can rename this to anything you want but this class is what you should be saving and loading. You can pass this `RootObject` class to my `DataSaver` class from the duplicate to save and load json. This simplifies the saving stuff. – Programmer Aug 08 '18 at 17:35
  • I got everything working except the overloaded function with prettyPrint don't work. So I used the other option without the prettyPrint and it seems to save the items correctly. – James Leshko Aug 08 '18 at 18:44
  • This is not a duplicate. This question specifies Newtonsoft which excludes most of the other answers that seem to miss that fact. – rainabba Jun 01 '22 at 20:09

0 Answers0