2

I'm using Json.net from newtonsoft.

Currently I'm learning myself alternatives for database storage. I'm 2 days stuck with the following problem:

I would like to save data local on JSON format. I have the currently the following (xml) structure:

<? xml version="1.0"?>
<data>
    <transactions>
        <transaction>
            <id>1</id>
            <type>1</type>
            <name>a name</name>
            <datetime>01-01-2017 00:00</datetime>
            <amount>34,05</amount>
        </transaction>
        <transaction>
            <id>2</id>
            <type>type2</type>
            <name>test transaction 2</name>
            <datetime>01-02-2017 00:00</datetime>
            <amount>23,03</amount>
        </transaction>
    </transactions>
    <categories>
        <category>
            <id>1</id>
            <name>cat 1</name>
            <description>a desc for cat 1</description>
            <color>red</color>
            <subcategories>
                <subcategory>
                    <id>1</id>
                    <name>subcat 1</name>
                    <description>a desc for subcat 1</description>
                    <color>blue</color>
                </subcategory>
                <subcategory>
                    <id>2</id>
                    <name>subcat 2</name>
                    <description>a desc for subcat 2</description>
                    <color>yellow</color>
                </subcategory>
            </subcategories>
        </category>
        <category>
            <id>2</id>
            <name>cat 2</name>
            <description>a desc for cat 1</description>
            <color>red</color>
        </category>
    </categories>
</data>

When I convert the following to JSON structure:

 {
  "data": {
    "transactions": {
      "transaction": [
        {
          "id": "1",
          "type": "1",
          "name": "a name",
          "datetime": "01-01-2017 00:00",
          "amount": "34,05"
        },
        {
          "id": "2",
          "type": "type2",
          "name": "test transaction 2",
          "datetime": "01-02-2017 00:00",
          "amount": "23,03"
        }
      ]
    },
    "categories": {
      "category": [
        {
          "id": "1",
          "name": "cat 1",
          "description": "a desc for cat 1",
          "color": "red",
          "subcategories": {
            "subcategory": [
              {
                "id": "1",
                "name": "subcat 1",
                "description": "a desc for subcat 1",
                "color": "blue"
              },
              {
                "id": "2",
                "name": "subcat 2",
                "description": "a desc for subcat 2",
                "color": "yellow"
              }
            ]
          }
        },
        {
          "id": "2",
          "name": "cat 2",
          "description": "a desc for cat 1",
          "color": "red"
        }
      ]
    }
  }
}

The problem I currently have is that I can Read/write to a json file (with JSON.NET) But I can only write down one (C#) Object. If I try to add my subcategories to my categories I get weird results:

Code:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace jsontest
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            List<Category> Categorylist = new List<Category>();
            Category c;
            SubCategory sc;
            for (int i = 0; i < 5; i++)
            {
                // New category
                c = new Category
                {
                    id = i,
                    name = "Category " + i,
                    description = "Category description " + i,
                    color = Color.Red                  
                };

                //Creating a few sub categories
                if (i == 2 || i == 4)
                {
                    for (int j = 0; j < i; j++)
                    {
                        sc = new SubCategory
                        {
                            id = j,
                            name = "SubCategory " + j + "From Category with Id " + i,
                            description = "Subcategory description " + j + "from Category with Id " + i,
                            color = Color.Yellow
                        };
                        // Add subcategorie to category 
                        c.subcategories.Add(sc);
                    }
                }
                // Add to list
                Categorylist.Add(c);
            }

            string json = JsonConvert.SerializeObject(Categorylist, Newtonsoft.Json.Formatting.Indented);
            richTextBox1.AppendText(Environment.NewLine + json);
        }
    }

    public class Category
    {
        public int id { get; set; }
        public string name { get; set; }
        public string description { get; set; }
        public Color color { get; set; }
        public List<SubCategory> subcategories = new List<SubCategory>();
    }

    public class SubCategory
    {
        public int id { get; set; }
        public string name { get; set; }
        public string description { get; set; }
        public Color color { get; set; }
    }
}

Result:

[
  {
    "subcategories": [],
    "id": 0,
    "name": "Category 0",
    "description": "Category description 0",
    "color": "Red"
  },
  {
    "subcategories": [],
    "id": 1,
    "name": "Category 1",
    "description": "Category description 1",
    "color": "Red"
  },
  {
    "subcategories": [
      {
        "id": 0,
        "name": "SubCategory 0From Category with Id 2",
        "description": "Subcategory description 0from Category with Id 2",
        "color": "Yellow"
      },
      {
        "id": 1,
        "name": "SubCategory 1From Category with Id 2",
        "description": "Subcategory description 1from Category with Id 2",
        "color": "Yellow"
      }
    ],
    "id": 2,
    "name": "Category 2",
    "description": "Category description 2",
    "color": "Red"
  },
  {
    "subcategories": [],
    "id": 3,
    "name": "Category 3",
    "description": "Category description 3",
    "color": "Red"
  },
  {
    "subcategories": [
      {
        "id": 0,
        "name": "SubCategory 0From Category with Id 4",
        "description": "Subcategory description 0from Category with Id 4",
        "color": "Yellow"
      },
      {
        "id": 1,
        "name": "SubCategory 1From Category with Id 4",
        "description": "Subcategory description 1from Category with Id 4",
        "color": "Yellow"
      },
      {
        "id": 2,
        "name": "SubCategory 2From Category with Id 4",
        "description": "Subcategory description 2from Category with Id 4",
        "color": "Yellow"
      },
      {
        "id": 3,
        "name": "SubCategory 3From Category with Id 4",
        "description": "Subcategory description 3from Category with Id 4",
        "color": "Yellow"
      }
    ],
    "id": 4,
    "name": "Category 4",
    "description": "Category description 4",
    "color": "Red"
  }
]

Could someone help me on track?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
  • Related: [Deserializing JSON into one of several C# subclasses](https://stackoverflow.com/questions/11429546/deserializing-json-into-one-of-several-c-sharp-subclasses) – Cœur Sep 06 '19 at 10:05

2 Answers2

1

If I understand the question correctly, you want to keep the format of your JSON string after adding to it, the same as the first one. For this, you need to create the classes corresponding to your JSON. You can use this and then you can deserialize the JSON string to an object of RootObject class and can easily add Transactions and Categories. Here is an example of adding a new category (adding Transactions is pretty much the same):

var test = JsonConvert.DeserializeObject<RootObject>(json);
test.data.categories.category.Add(new Category() 
{
    id = "newId",
    name = "newName",
    color = "newColor",
    description = "new description",
    subcategories = new Subcategories() 
    { 
        subcategory = new List<Subcategory>() 
    }
});

The serialization of test gives you the new JSON string.

Mahdi
  • 3,199
  • 2
  • 25
  • 35
0

Problem is not with c# code. It's producing output as you have instructed to do. Problem is with conversion from xml to JSON. In converted JSON subcategories is not array of subcategory but its object having property "subcategory" and subcategory is "array" of objects of anonymous types. So if you want c# program to produce json structure which looks like converted json from xml then you need to change definition of Category class where "subcategories" property will not be of list type but another complex type with property called "subcategory" and in turn "subcategory" will be array/list of anonymous type.

Pankaj Kapare
  • 7,486
  • 5
  • 40
  • 56
  • HI, thanks for your reply. I will look into it. What do u suggest as an solution? Change the way to format JSON? Or should I change my format at all? The only thing I want to store is a large list of `Transactions`, and a few `Categories`, some categories may have `Subcategories` – Bram van den Hoek Jan 17 '17 at 13:11
  • I am not aware of exact context of use case however either way i.e. change JSON or change C# program should work. Whichever is suitable and easy for you should work. – Pankaj Kapare Jan 17 '17 at 13:33