Ashley
Ashley

Reputation: 579

How do I edit a json file in c#?

I am making a text adventure and whenever a player types "pick up the iron sword" or whatever, I need to be able to take the iron sword OUT of the JSON array within the room that it is kept in.

{
Rooms: [
    {
        id: "PizzaShop1",
        name: "Pizza Shop",
        description: "in a nice warm pizza shop that smells of garlic.",
        items: [
            {
                id: "HawaiianPizza1",
                name: "Hawaiian Pizza",
                description: "a pizza topped with ham and pineapple",
                strengthMod: 0,
                toughnessMod: 0
            },
            {
                id: "MeatloversPizza1",
                name: "Meatlovers Pizza",
                description: "a pizza topped with lots of meat",
                strengthMod: 0,
                toughnessMod: 0
            }
        ],
        entities: [
            {
                name: "Pizza Chef",
                description: "an italian man",
                friendly: true
            },
            {
                name: "Mouse",
                description: "a pesky mouse",
                friendly: false
            }
        ],
        northExit: "",
        southExit: "Road1",
        eastExit: "",
        westExit: ""
    },     
    {
        id: "Road1",
        name: "Road",
        description: "on a town road",
        items: [
            {
                id: "IronSword1",
                name: "Iron Sword",
                description: "a battered but usable sword",
                strengthMod: 2,
                toughnessMod: 0
            }
        ],
        entities: [],
        northExit: "PizzaShop1",
        southExit: "",
        eastExit: "",
        westExit: ""
    }
]
}

And here is my c# code:

                else if (s.Contains(" pick up "))
            {
                String newJson = "";
                s = s.Replace(" the ", " ");
                s = s.Replace(" pick ", " ");
                s = s.Replace(" up ", " ");
                String[] Words = s.Split(' ');
                foreach (String word in Words)
                {
                    if (word != Words[1])
                    {
                        Words[1] = Words[1] + " " + word;
                        Words[1] = Words[1].Replace("  ", " ");
                        Words[1] = Words[1].Trim();
                    }
                }
                using (StreamReader sr = new StreamReader("TAPResources/map.json"))
                {
                    String json = sr.ReadToEnd();
                    dynamic array = JsonConvert.DeserializeObject(json);
                    foreach (var rooms in array["Rooms"])
                    {
                        foreach (var item in rooms["items"])
                        {
                            String itm = (String)item["name"];
                            PrintMessage("Words: " + Words[1]);
                            PrintMessage("Item Name: " + itm.ToLower());
                            if (Words[1] == itm.ToLower())
                            {
                                rooms["items"].Remove(item);
                            }
                        }
                    }
                    newJson = (String)JsonConvert.SerializeObject(array);
                }
                File.WriteAllText("TAPResources/map.json", newJson);
            }

The line:

rooms["items"].Remove(item);

Gives an error, because I can't edit the array within the loop. Normally I would solve this by adding the value to another array, then iterating through that array to remove from the initial array, but I don't know how to make an array for that variable type.

Upvotes: 3

Views: 7845

Answers (2)

SilentTremor
SilentTremor

Reputation: 4902

Ok so here we go, ideally is recommended to use well defined objects (classes) case using dynamic objects is a slower processing, any how:

dynamic array = GetRooms();

    foreach (var rooms in array["Rooms"])
    {
        List<object> list = new List<object>();
        foreach (var item in rooms["items"])
        {
            string itm = (string) item["name"];
            if (!"hawaiian pizza".Equals(itm.ToLower()))
            {
                list.Add(item);
            }
        }
        //u can use this 
        //from rooms in array["Rooms"] select rooms where (true something)
        //or what I did case I'm lazy
        //Newtonsoft.Json.Linq.JToken transfor or you can use linq to dow whatever 
        rooms["items"] = JsonConvert.DeserializeObject<JToken>(JsonConvert.SerializeObject(list.ToArray()));
    }
    Console.Write(JsonConvert.SerializeObject(array));

Upvotes: 2

cnaegle
cnaegle

Reputation: 1125

You probably want to add classes that represent the game, rooms and items, and then keep them in memory while the game is playing. When they save the game you can serialize it back into JSON. It is easier to work with objects than to try and loop through the whole document rooms and each of the items to find one item and remove it.

I would suggest the following classes based on your Json document:

public class Item
{
    public string id { get; set; }
    public string name { get; set; }
    public string description { get; set; }
    public int strengthMod { get; set; }
    public int toughnessMod { get; set; }
}

public class Room
{
    public string id { get; set; }
    public string name { get; set; }
    public string description { get; set; }
    public List<Item> items { get; set; }
    public List<object> entities { get; set; }
    public string northExit { get; set; }
    public string southExit { get; set; }
    public string eastExit { get; set; }
    public string westExit { get; set; }
}

public class Game
{
    public List<Room> Rooms { get; set; }
}

Then you can deserialize your JSON into a Game object like this:

var game = JsonConvert.DeserializeObject<Game>(json);

Then if you want to remove the sword from the "Road1" room it's much more concise than looping through the dynamic object:

//Find room by id and remove item by id
game.Rooms.Single(room => room.id == "Road1")
    .items.RemoveAll(item => item.id == "Iron Sword");

//Turn the game object back into a Json string
var json = JsonConvert.SerializeObject(game);

//now write json string back to storage...

This gives you more flexibility during runtime. For example, it becomes really easy to add a new room on the fly:

var room = new Room
        {
            id = "new room",
            name = "very cool room",
            description = "A very cool room that was added on the fly",
            items = new List<Item> 
                        { 
                          new Item 
                               { 
                                 id = "another sword", 
                                 description = "Another battered sword"
                                 //etc...
                                } 
                          }
            //etc...
        }

game.Rooms.Add(room);

Hope this helps.

Upvotes: 2

Related Questions