将JObject添加到JArray

时间:2019-09-14 21:14:00

标签: c# json

我正在尝试将一个名为“ Company”的新类添加到一个名为Companies的Json Array中。我正在使用C#和Json .net进行此操作。我尝试了许多不同的方法。我把它们全部砍掉了,并准备好将它们放入Jobjects中,但是我找不到办法。我试图让它找到“公司”,然后在其中插入新的公司对象。

这就是我想做的。

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);
}

这些是课程

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; }
}

这就是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
   ]
}

2 个答案:

答案 0 :(得分:0)

这应该使您对应该做的事情有所了解

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);
    }
}

删除现有的json文件,然后运行此代码。第一次运行使用一个对象创建文件,而随后的运行向其添加对象。您可以重构代码。

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
    }
  ]
}

根据您对订单的评论,您可以像下面这样在课堂上设置订单

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>();
}

答案 1 :(得分:0)

JSON文件只是文本文件,因此没有直接的方法将记录插入文件的中间。相反,您需要将整个文件加载到某种内存中表示形式,将Company添加到"Companies"数组,然后将文件重新序列化回磁盘。

要实现此目的,请首先创建以下扩展方法:

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);
        }           
    }
}

现在,您可以将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);

演示小提琴#1 here

顺便说一句,由于您的整个文件似乎都具有固定的架构,因此可以通过直接反序列化到某些根数据模型来简化整个代码并获得略微更好的性能,而完全省略JObject表示形式。

首先,创建以下根数据模型:

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

然后按如下所示修改CreateNewCompany()

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

root.Companies.Add(company);

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

演示小提琴#2 here

注意:

  • 通过在JsonExtensions中使用泛型,我们可以为JObjectCompanyList使用相同的代码从文件加载并保存到文件。

  • 直接从文件到文件的序列化而不加载到中间string会提高性能,如 Performance Tips: Optimize Memory Usage 中所述。

  • Company.StartDate被声明为int,但是在您的JSON中它显示为非数字string

    "StartDate": "1-1-2000"
    

    您将需要调整数据模型以解决此问题。

  • 由于File.CreateText(String) 创建或打开用于写入UTF-8编码文本的文件,因此无需手动删除旧文件。如果文件已经存在,则其内容将被覆盖。

    或者,您可能要写入一个临时文件,然后仅在序列化成功完成之后才覆盖旧文件。

  • 最好从FileNotFoundException中捕获File.OpenText(),而不要手动检查File.Exists(),以防在两次调用之间文件被删除。

    < / li>