简体   繁体   English

将JObject添加到JArray

[英]Adding JObject to JArray

Im trying to add a new class called "Company" to a Json Array called Companies. 我试图将一个名为“ Company”的新类添加到名为“公司”的Json Array中。 I'm doing this using C# and Json .net Ive tried many different things. 我正在使用C#和Json .net进行此操作。我尝试了许多不同的方法。 I have them all pares out and in Jobjects ready to be molded together but I can't find a way to do so. 我把它们全部砍掉了,并准备好将它们放入Jobjects中,但是我找不到办法。 Im trying to get it to find "Companies" then insert the new company object in there. 我试图让它找到“公司”,然后在其中插入新的公司对象。

This is what im trying to do. 这就是我想做的。

public void CreateNewCompany()
{
    Company company = new Company
    {
        CompanyName = textBox1.Text,
        IPO = Convert.ToDouble(textBox2.Text),
        Category = CategorycomboBox1.SelectedItem.ToString(),
        Description = textBox4.Text,
        StartDate = Convert.ToInt32(textBox5.Text)
    };

    AddProductListItemsToFinishedJSON(company);
    AddNewsArticlesListItemsToFinishedJSON(company);

    JObject newCompany = JObject.FromObject(company);

    string existingFileContents = File.ReadAllText(path);
    string newFileContents      = newCompany.ToString();          

    var existingFileContentsToJSON = JObject.Parse(existingFileContents);
    var newFileContentsToJSON      = JObject.Parse(newFileContents);

    Debug.WriteLine(existingFileContents);

    SaveJSONFile(company);
}

public void SaveJSONFile(Company localcompany)
{
    if (File.Exists(Path.Combine(@"D:\", "comp.json")))
    {
        File.Delete(Path.Combine(@"D:\", "comp.json"));
    }       

    string RawJSON       = JsonConvert.SerializeObject(localcompany);
    string FormattedJSON = JToken.Parse(RawJSON).ToString(Formatting.Indented);

    //Console.WriteLine(FormattedJSON);
    File.WriteAllText(@"D:\comp.json", FormattedJSON);
}

These are the classes 这些是课程

public class Company
{
    public string CompanyName { get; set; }
    public double IPO { get; set; }
    public string Category { get; set; }
    public string Description { get; set; }
    public int    StartDate { get; set; }

    public List<Product> Products                        = new List<Product>();
    public List<NewsArticle> CompanySpecificNewsArticles = new List<NewsArticle>();
    public List<string> EavesDropperList = new List<string>();
}

public class Product
{
    [JsonProperty("ProductName")]
    public string ProductName { get; set; }
}

public class NewsArticle
{
    [JsonProperty("Type")]
    public string Type { get; set; }

    [JsonProperty("Content")]
    public string Content { get; set; }
}

This is what the Json Looks like and I want to add it to 'Companies' 这就是Json的样子,我想将其添加到“公司”中

{
   "Companies":[
      {
         "CompanyName":"",
         "IPO":25.0,
         "Category":"Gaming",
         "Description":"A video game company",
         "StartDate":"1-1-2000",
         "Products":[
            {
               "ProductName":""
            },
            {
               "ProductName":""
            }
         ],
         "CompanySpecificNewsArticles":[
            {
               "Type":"Positive",
               "Content":"This company has had a very good year!"
            },
            {
               "Type":"Negative",
               "Content":"This company has had a very bad year!"
            },
            {
               "Type":"Neutral",
               "Content":"This company is doing okay, I guess"
            }
         ],
         "CompanySpecificEavesdropper":[
            {
               "Type":"Positive",
               "Content":"This company has had a very good year!"
            },
            {
               "Type":"Negative",
               "Content":"This company has had a very bad year!"
            },
            {
               "Type":"Neutral",
               "Content":"This company is doing okay, I guess!"
            }
         ]
      }
      //,
      // Other companies omitted
   ]
}

This should give you an idea of what you should be doing 这应该使您对应该做什么有所了解

public void CreateNewCompany()
{
    Company company = new Company
    {
        CompanyName = "New Company",
        IPO = Convert.ToDouble("0.2"),
        Category = "Sample Category",
        Description = "Sample Description",
        StartDate = Convert.ToInt32("2009")
    };

    AddProductListItemsToFinishedJSON(company);
    AddNewsArticlesListItemsToFinishedJSON(company);

    SaveJSONFile(company);

}

public static void SaveJSONFile(Company localcompany)
{
    if (File.Exists(path))
    {
        JObject arr = JObject.Parse(File.ReadAllText(path)));
        (arr["Companies"] as JArray).Add(JToken.FromObject(localcompany));
        string RawJSON = JsonConvert.SerializeObject(arr);
        string FormattedJSON = JToken.Parse(RawJSON).ToString(Formatting.Indented);
        File.WriteAllText(path, FormattedJSON);
    }
    else
    {
        JObject arr = new JObject();
        arr.Add("Companies", new JArray());
        (arr["Companies"] as JArray).Add(JToken.FromObject(localcompany));
        string RawJSON = JsonConvert.SerializeObject(arr);
        string FormattedJSON = JToken.Parse(RawJSON).ToString(Formatting.Indented);
        File.WriteAllText(path, FormattedJSON);
    }
}

Delete your existing json file then run this code. 删除您现有的json文件,然后运行此代码。 The first run creates the file with one object while subsequent runs adds object to it. 第一次运行使用一个对象创建文件,而随后的运行向其添加对象。 You can refactor the code. 您可以重构代码。

Json file will have the format below Json文件将具有以下格式

{
  "Companies": [
    {
      "Products": [],
      "CompanySpecificNewsArticles": [],
      "EavesDropperList": [],
      "CompanyName": "New Company",
      "IPO": 0.2,
      "Category": "Sample Category",
      "Description": "Sample Description",
      "StartDate": 2009
    },
    {
      "Products": [],
      "CompanySpecificNewsArticles": [],
      "EavesDropperList": [],
      "CompanyName": "New Company",
      "IPO": 0.2,
      "Category": "Sample Category",
      "Description": "Sample Description",
      "StartDate": 2009
    }
  ]
}

as per your comment on the order, you can set order on you class like below 根据您对订单的评论,您可以像下面这样在课堂上设置订单

public class Company
{
    [JsonProperty(Order = 0)]
    public string CompanyName { get; set; }
    [JsonProperty(Order = 1)]
    public double IPO { get; set; }
    [JsonProperty(Order = 2)]
    public string Category { get; set; }
    [JsonProperty(Order = 3)]
    public string Description { get; set; }
    [JsonProperty(Order = 4)]
    public int StartDate { get; set; }
    [JsonProperty(Order = 5)]

    public List<Product> Products = new List<Product>();
    [JsonProperty(Order = 6)]
    public List<NewsArticle> CompanySpecificNewsArticles = new List<NewsArticle>();
    [JsonProperty(Order = 7)]
    public List<string> EavesDropperList = new List<string>();
}

A JSON file is just a text file, so there's no straightforward way to insert a record into the middle of the file. JSON文件只是一个文本文件,因此没有直接的方法将记录插入文件的中间。 Instead, you will need to load the entire file into some in-memory representation, add your Company to the "Companies" array, then re-serialize the file back to disk. 相反,您需要将整个文件加载到某种内存中表示形式,将Company添加到"Companies"数组中,然后将文件重新序列化回磁盘。

To accomplish this, first create the following extension methods: 为此,首先创建以下扩展方法:

public class JsonExtensions
{
    public static T LoadFromFileOrCreateDefault<T>(string path, JsonSerializerSettings settings = null) where T : new()
    {
        var serializer = JsonSerializer.CreateDefault(settings);

        try
        {
            using (var file = File.OpenText(path))
            {
                return (T)JsonSerializer.CreateDefault(settings).Deserialize(file, typeof(T));
            }
        }
        catch (FileNotFoundException)
        {
            return new T();
        }
    }

    public static void SaveToFile<T>(T root, string path, Formatting formatting = Formatting.None, JsonSerializerSettings settings = null)
    {
        using (var file = File.CreateText(path))
        using (var writer = new JsonTextWriter(file) { Formatting = formatting })
        {
            JsonSerializer.CreateDefault(settings).Serialize(writer, root);
        }           
    }
}

Now you can add your Company to the array in CreateNewCompany() as follows: 现在,您可以将Company添加到数组中的CreateNewCompany() ,如下所示:

var root = JsonExtensions.LoadFromFileOrCreateDefault<JObject>(Path);

var companiesArray = (JArray)root["Companies"] ?? (JArray)(root["Companies"] = new JArray());

companiesArray.Add(JObject.FromObject(company));

JsonExtensions.SaveToFile(root, Path, Formatting.Indented);

Demo fiddle #1 here . 演示小提琴#1 在这里

Incidentally, since your entire file seems to have a fixed schema, you could simplify your code and get slightly better performance by deserializing directly to some root data model, omitting the JObject representation entirely. 顺便说一句,由于您的整个文件似乎都具有固定的架构,因此可以通过直接反序列化到某些根数据模型来简化整个代码并获得略微更好的性能,而完全省略JObject表示。

First, create the following root data model: 首先,创建以下根数据模型:

public class CompanyList
{
    public List<Company> Companies { get; } = new List<Company>();
}

Then modify CreateNewCompany() as follows: 然后,如下修改CreateNewCompany()

var root = JsonExtensions.LoadFromFileOrCreateDefault<CompanyList>(Path);

root.Companies.Add(company);

JsonExtensions.SaveToFile(root, Path, Formatting.Indented);

Demo fiddle #2 here . 演示小提琴#2 在这里

Notes: 笔记:

  • By using generics in JsonExtensions we can use the same code to load from, and save to, a file, for both JObject and CompanyList . 通过在JsonExtensions使用泛型,我们可以使用相同的代码从JObjectCompanyList加载并保存到文件。

  • Serializing directly from and to your file without loading to an intermediate string should improve performance as explained in Performance Tips: Optimize Memory Usage . 性能提示:优化内存使用中所述,直接在文件中进行序列化而不加载到中间string应可以提高性能。

  • Company.StartDate is declared to be an int , however in your JSON it appears as a non-numeric string : Company.StartDate被声明为int ,但是在您的JSON中,它显示为非数字string

     "StartDate": "1-1-2000" 

    You will need to adjust your data model to account for this. 您将需要调整数据模型以解决此问题。

  • There is no need to manually delete the old file as File.CreateText(String) creates or opens a file for writing UTF-8 encoded text. 由于File.CreateText(String) 创建或打开用于写入UTF-8编码文本的文件, File.CreateText(String)无需手动删除旧文件 If the file already exists, its contents are overwritten. 如果文件已经存在,则其内容将被覆盖。

    Alternatively you might want to write to a temporary file and then overwrite the old file only after serialization finishes successfully. 另外,您可能要写入一个临时文件,然后仅在序列化成功完成后才覆盖旧文件。

  • It is better to catch the FileNotFoundException from File.OpenText() rather than checking File.Exists() manually in case the file is somehow deleted in between the two calls. 最好从File.OpenText()捕获FileNotFoundException ,而不是手动检查File.Exists() ,以防在两次调用之间删除文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM