有没有办法在 JSON 文件的值中获取键名

Posted

技术标签:

【中文标题】有没有办法在 JSON 文件的值中获取键名【英文标题】:Is there a way to get the key name in value of JSON file 【发布时间】:2020-12-09 08:04:01 【问题描述】:

我想根据键名填充属性。例如。物理地址的地址类型将是物理地址。目前我正在使用 Newtonsoft.Json。此信息将使用 EntityFramework 存储在数据库中。

谢谢

这是 JSON 文件的示例部分:

"person": [
  
    "physicalAddress": [
      
        "address": "123 Street Name",
        "postCode": 1122
      
    ],
    "postalAddress": [
      
        "address": "123 Street Name",
        "postCode": 1122
      
    ],
    "registeredAddress": [
      
        "address": "123 Street Name",
        "postCode": 1122
      
    ]
  

这是该类的一个示例部分:

    [JsonProperty("address")]
    public string Address  get; set; 

    [JsonProperty("postCode")]
    public string PostCode  get; set; 

    public string AddressType  get; set; 

【问题讨论】:

您需要自定义序列化代码(例如JsonConverter 也许创建一个具有AddressType 只读属性的PhysicalAddress 类(postalAddress 等也一样)? 这些类中的每一个都可以从具有抽象只读AddressType 属性的抽象类继承。 你的 JSON 中的physicalAddress 真的打算作为一个数组还是一个对象?因为在您的示例中,它就像一个数组。但我提出这个问题是为了让我们确定为实现您的目标而做的正确事情。 【参考方案1】:

假设您不想或不能更改客户端,一种可能的方法是创建一个与请求正文的格式相匹配的请求模型,即

  [JsonProperty("physicalAddress")]
  public List<AddressRequestModel> PhysicalAddress  get; set; 

  [JsonProperty("postalAddress")]
  public List<AddressRequestModel> PostalAddress get; set; 

  [JsonProperty("registeredAddress")]
  public List<AddressRequestModel> RegisteredAddress get; set; 

其中AddressRequestModel 将是包含属性AddressPostCode 的类。然后当收到请求时,将请求模型映射到您的应用程序所需的模型。在映射器中,您可以分配适当的地址类型,即


public class AddressMapper

   public List<AddressRequestModel> Map(RequestModel model)
   
      var addresses = new List<AddressRequestModel>();
      model.PhysicalAddress.ForEach(address => addresses.Add(Map(address, "physicalAddress"));
      model.PostalAddress.ForEach(address => addresses.Add(Map(address, "postalAddress"));
      model.RegisteredAddress.ForEach(address => addresses.Add(Map(address, "registeredAddress"));
      return addresses;
   

   private AddressRequestModel Map(AddressRequestModel model, string addressType) =>
   new AddressRequestModel
   
       Address = model.Address,
       PostCode = model.PostCode,
       AddressType = addressType,
   

【讨论】:

【参考方案2】:

我创建了一个有点复杂的案例来通过 JsonConverter 解析这个 json。它可以满足您的要求。

主函数使用JProperty动态获取地址键名(physicalAddress、postalAddress等),Children()获取子节点。

class Program


    static void Main(string[] args)
    
         string json = @"
""person"": [
  
    ""physicalAddress"": [
      
        ""address"": ""123 Street Name"",
        ""postCode"": 1122
      ,
      
        ""address"": ""456 Street Name"",
        ""postCode"": 7788
      
    ],
    ""postalAddress"": [
      
        ""address"": ""123 Street Name"",
        ""postCode"": 1122
      ,
      
        ""address"": ""9999 Street Name"",
        ""postCode"": 77886666
      
    ],
    ""registeredAddress"": [
      
        ""address"": ""123 Street Name"",
        ""postCode"": 1122
      ,
      
        ""address"": ""fwerg Street Name"",
        ""postCode"": 9999999
      

    ]
  
  
  ]

";

         Person person = JsonConvert.DeserializeObject<Person>(json, new MyTypeConverter());
     


public class Person

    public List<AddressDetail> Addresses  get; set; 


public class AddressDetail

    public string Address  get; set; 

    public string PostCode  get; set; 

    public string AddressType  get; set; 


public class MyTypeConverter : JsonConverter

    public override bool CanConvert(Type objectType)
    
        return typeof(Person).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo());
    

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    
        if (reader.TokenType == JsonToken.StartObject)
        
            JObject item = JObject.Load(reader);
            if (item["person"] != null)
            
                var pseron = new Person()
                
                    Addresses = new List<AddressDetail>()
                ;
                var largeAddressArr = item["person"].Children();
                foreach (var largeAddress in largeAddressArr)
                
                    foreach (var keyAddress in largeAddress.Children())
                    
                        string keyName = (keyAddress as JProperty).Name;
                        List<JToken> tokens = keyAddress.Children().ToList();
                        foreach (var address in tokens)
                        
                            var addresses = address.ToObject<List<AddressDetail>>();
                            addresses.ForEach(x => x.AddressType = keyName);
                            pseron.Addresses.AddRange(addresses);
                        
                    
                

                return pseron;
            
        
        return null;
    

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    
        throw new NotImplementedException();
    

【讨论】:

以上是关于有没有办法在 JSON 文件的值中获取键名的主要内容,如果未能解决你的问题,请参考以下文章

使用 jq 从 JSON 文件中递归获取键名

从 JSON 中获取键名和值名并在 Highcharts 中使用

我如何通过在这里进行字符串拆分来获取 json 键名? (Python)

如何使用 jq 从 JSON 中获取键名

如何使用json方法解析android中没有键名的数组内的嵌套json编码数组?

如何从 BigQuery 中的 Array(Struct) 类型数据结构中获取每个键名的值