在C#中使用JSON Path动态创建JSON对象

问题描述 投票:0回答:1

我有一个 json 属性路径及其值的键值对列表,

Key: $.orderNumber                                      Value: "100001"
Key: $.orderedOn                                        Value: "01-01-2021"
Key: $.product.name                                     Value: "hard"
Key: $.product.type                                     Value: "plastic" 
Key: $.contacts[?(@.contactType == 'primary')].phone    Value: "101010101010" 
Key: $.contacts[?(@.contactType == 'secondary')].phone  Value: "2020202020"

并且想要创建一个 JSON 对象或 JSON 字符串,如下所示

{
  "orderNumber": "100001",
  "orderedOn": "01-01-2021",
  "product": {
    "type": "hard",
    "name": "plastic"
  },
  "contacts": [
    {
      "contactType": "primary",
      "phone": "101010101010"
    },
    {
      "contactType": "secondary",
      "phone": "202020202020"
    }
  ]
}

是否可以使用 JSON PATH 创建 JSON 对象,或者我需要手动检查写入所有属性?

我想动态创建 JSON 对象。

我尝试过 Json.net Unflatten,但它没有覆盖条件数组键。

c# json json.net .net-5
1个回答
0
投票

静态解决方案:

没有找到动态解决方案,所以我创建了一个静态解决方案:

型号: 定义表示 JSON 对象结构的 C# 类。

class Order
{
    public string OrderNumber { get; set; }
    public string OrderedOn { get; set; }
    public Product Product { get; set; }
    public List<Contact> Contacts { get; set; }
}

class Product
{
    public string Type { get; set; }
    public string Name { get; set; }
}

class Contact
{
    public string ContactType { get; set; }
    public string Phone { get; set; }
    public string Address { get; set; }
}

M拍打功能: 将 JSON 路径和值映射到 Order 对象中的相应属性。

Order MapOrderObjectWithJsonPath(Order order, string jsonPath, string value)
{
    // First initialize the order object if necessary for nested objects.
    InitializeObjects(order, jsonPath);

    // Use switch-case for better performance.
    switch (jsonPath)
    {
        case "$.orderNumber":
            order.OrderNumber = value;
            break;
        case "$.orderedOn":
            order.OrderedOn = value;
            break;
        case "$.product.type":
            order.Product.Type = value;
            break;
        case "$.product.name":
            order.Product.Name = value;
            break;

        // In my case, contact type is an identifier.
        case "$.contacts[?(@.contactType == 'primary')].phone":
            order.Contacts.FirstOrDefault(x => x.ContactType == "primary").Phone = value;
            break;
        case "$.contacts[?(@.contactType == 'primary')].address":
            order.Contacts.FirstOrDefault(x => x.ContactType == "primary").Address = value;
            break;
        case "$.contacts[?(@.contactType == 'secondary')].phone":
            order.Contacts.FirstOrDefault(x => x.ContactType == "secondary").Phone = value;
            break;
        case "$.contacts[?(@.contactType == 'secondary')].address":
            order.Contacts.FirstOrDefault(x => x.ContactType == "secondary").Address = value;
            break;
    }
}

对象初始化: 基于 JSON 路径初始化嵌套对象(产品、联系人)。

public void InitializeObjects(Order order, string jsonPath)
{
    // Initialize the product object if it is not initialized before.
    if (jsonPath.Contains(".product.") && order.Product == null)
        order.Product = new Product();

    // For the contacts array, initialize and check the respective contact element.
    // If it is not in the list mentioned in the JSON path, create that element and add it to the contact list.
    else if (jsonPath.Contains("$.contacts[?(@.contactType == 'primary')]"))
    {
        if (order.Contacts == null) order.Contacts = new List<Contact>();

        if (!order.Contacts.Any(x => x.ContactType.Equals("primary")))
        {
            Contact primaryContact = new Contact();
            primaryContact.ContactType = "primary";
            order.Contacts.Add(primaryContact);
        }
    }
    else if (jsonPath.Contains("$.contacts[?(@.contactType == 'secondary')]"))
    {
        if (order.Contacts == null) order.Contacts = new List<Contact>();

        if (!order.Contacts.Any(x => x.ContactType.Equals("secondary")))
        {
            Contact secondaryContact = new Contact();
            secondaryContact.ContactType = "secondary";
            order.Contacts.Add(secondaryContact);
        }
    }
}

用途:

using Newtonsoft.Json;

// Create an empty Order object 
Order order = new Order();

// List of JSON paths and corresponding values, considering that you have that in a list. 
List<(string jsonPath, string value)> jsonPathValues = new List<(string, string)>
{
    // Add your JSON paths and values here
    // Example: ("$.orderNumber", "100001"),
};

// Loop through each JSON path and value, mapping them to the order object.
foreach (var (jsonPath, value) in jsonPathValues)
{
    // Map the JSON path and value to the existing Order object
    MapOrderObjectWithJsonPath(order, jsonPath, value);
}

// Serialize the 'order' object into JSON with settings to handle null values for empty objects
string json = JsonConvert.SerializeObject(order, Formatting.None, new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore
});

// Now 'json' has the result
© www.soinside.com 2019 - 2024. All rights reserved.