【问题标题】:Is there a way to get the key name in value of JSON file有没有办法在 JSON 文件的值中获取键名
【发布时间】: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 真的打算作为一个数组还是一个对象?因为在您的示例中,它就像一个数组。但我提出这个问题是为了让我们确定为实现您的目标而做的正确事情。

标签: c# json entity-framework json.net


【解决方案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();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-20
      • 1970-01-01
      相关资源
      最近更新 更多