Home > Software engineering >  Get information out of a JSON like file in c# (.NET 4.8)
Get information out of a JSON like file in c# (.NET 4.8)

Time:10-23

I'm currently still learning c# and im trying to find the best method to get the information out. Tried Regex and even thought of using JSON but im pretty sure there is a simpler method. I have data like this:

Main_name = {
    # Comment
    # Comment
    # Comment
    type1 = uselessname_importantNumber                                (e.g. ryu_3)
    type2 = "path" # Comment
    type3 = name
    type4 = true

    type5 = {
        name2
        name3...
        # Comment
    }
}

My objective is to store the values: Main_name, importantNumber, path, name, true, list of names in type5 in a List.

Currently im doing

TechData = new List<ClassTech>();

            string[] paths = Directory.GetFiles(path, "*.txt");

            foreach (string pathsl in paths)
            {

                using (StreamReader sr = File.OpenText(pathsl))
                {
                    string line;
                    int i = 0;
                    string[] words;



                    while ((line = sr.ReadLine()) != null)
                    {


                        if (line.Contains("{") == true && !line.Contains("#"))
                        {

                            // Get's the name
                            words = line.Split('=');
                            TechData.Add(new ClassTech(words[0].Trim(' '), "None", -1, null, "None", null, true));


                            // In {}
                            while ((line = sr.ReadLine()) != null)
                            {
                                if ((Regex.Match(line, @"\bera\b")).Success && (TechData[i].era == -1) && !line.Contains("#"))
                                {
                                    words = line.Split('=');
                                    TechData[i].era = words[1][words[1].Length - 1] - 48;

                                }
                                else if ((Regex.Match(line, @"\btexture\b")).Success && (TechData[i].texture == null) && !line.Contains("#"))
                                {
                                    words = line.Split('=');
                                    TechData[i].texture = words[1].Trim(' ', '"');

                                }
                                else if ((Regex.Match(line, @"\bcategory\b")).Success && (TechData[i].category == null) && !line.Contains("#"))
                                {
                                    words = line.Split('=');
                                    TechData[i].category = words[1].Trim(' ');

                                }
                                else if ((Regex.Match(line, @"\bcan_research\b")).Success && (Regex.Match(line, @"\bno\b")).Success && !line.Contains("#"))
                                {
                                    TechData[i].canResearch = false;

                                }
                                else if ((Regex.Match(line, @"\bmodifier\b")).Success && !line.Contains("#"))
                                {
                                    while ((line = sr.ReadLine()) != null)
                                    {
                                        if (line.Contains("}")) { break; }
                                        else if (line.Contains("="))
                                        {
                                            TechData[i].modifiers.Add(line.Trim(' '));
                                        }
                                        else { }


                                    }

                                }
                                else if ((Regex.Match(line, @"\bunlocking_technologies\b")).Success && !line.Contains("#"))
                                {
                                    while ((line = sr.ReadLine()) != null)
                                    {
                                        if (line.Contains("}")) { break; }
                                        else if (!string.IsNullOrEmpty(line) && !string.IsNullOrWhiteSpace(line))
                                        {
                                            TechData[i].restrictions.Add(line.Trim('\t'));
                                        }
                                        else { }
                                    }
                                }
                                else if (line.Contains("}") == true)
                                {
                                    break;
                                }
                                else
                                {
                                }

                            }
                            i  ;
                        }


                    }





                }
            }

The problem is if the data becomes bigger, it will start to become harder and harder so my question is: is there a simpler way to do it and if possible faster?

Data example

sericulture = {
    # Unlocks Mulberry Groves PM on Rice Farms
    era = era_1
    texture = "gfx/interface/icons/invention_icons/sericulture.dds"
    category = production
    can_research = no
    
    modifier = {
        building_silk_plantation_throughput_mult = 0.25
        
    }
}

enclosure = {
    # Unlocks construction of Farms and Plantations
    era = era_1
    texture = "gfx/interface/icons/invention_icons/enclosure.dds"
    category = production
}

manufacturies = {
    # Unlocks Mercantilism Law
    # Unlocks Food Industry, Textile Mills, Furniture Manufacturies, Glassworks, Tooling Workshops, Paper Mills
    era = era_1
    texture = "gfx/interface/icons/invention_icons/manufacturies.dds"
    category = production
}

shaft_mining = {
    # Unlocks Coal Mine, Iron Mine, Lead Mine, Sulfur Mine
    era = era_1
    texture = "gfx/interface/icons/invention_icons/shaft_mining.dds"
    category = production
    
    unlocking_technologies = {
        enclosure
        manufacturies
    }
}

atmospheric_engine = {
    # Unlocks Motor Industry
    # Unlocks Atmospheric Engine Pump PM in Coal Mine, Iron Mine, Lead Mine, Sulfur Mine
    era = era_1
    texture = "gfx/interface/icons/invention_icons/atmospheric_engine.dds"
    category = production
    
    unlocking_technologies = {
        shaft_mining
    }
}

CodePudding user response:

I broadly agree with @Jon Skeet's suggestion to convert these files to JSON. If you can do that at the source, do it.

If not, you'll either have to convert it yourself, or parse the data some other way.

Regardless, if you want this to be expandable, your goal should be to be able to get this data into C# without relying on beforehand knowledge of any property names.

I've put together a parser based on the example files you've left above. It's not perfect, but it should be a strong starting point:

The full project, and the primary parsing logic

It works by parsing the input file to a string-keyed dictionary containing values of Dictionary<string,object?>, List<string>, or object?.

Note: if you want to convert this JSON data to C# objects afterwards, go for it. It'll be much simpler once it's in JSON form, since there are many tools for that.

Example usage

SourceFile.txt

Main_name = {
    # Comment
    # Comment
    # Comment
    type1 = ryu_3
    type2 = "path" # Comment
    type3 = name
    type4 = true

    type5 = {
        name2
        name3...
        # Comment
    }
}

Program.cs

var outVal = new ObjectParserThing.ObjectParserThing().ParseFile("sourceFile.txt");

Console.WriteLine(JsonSerializer.Serialize(outVal, new JsonSerializerOptions {
    WriteIndented = true,
}));

Output

{
  "Main_name": {
    "type1": "ryu_3",
    "type2": "\u0022path\u0022",
    "type3": "name",
    "type4": "true",
    "type5": [
      "name2",
      "name3..."
    ]
  }
}
  •  Tags:  
  • c#
  • Related