#c# #json #entity-framework #json.net
#c# #json #entity-framework #json.net
Вопрос:
Я хочу заполнить свойство на основе имени имени ключа. Например. Типом адреса для физического адреса будет PhysicalAddress. В настоящее время я использую 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; }
Комментарии:
1. Вам понадобится пользовательский код сериализации (например, a
JsonConverter
)2. Возможно, создать
PhysicalAddress
класс, который имеет свойство только для чтенияAddressType
(и то же самое дляpostalAddress
etc)? Каждый из этих классов может наследоваться от абстрактного класса с абстрактным свойством только для чтенияAddressType
.3. Физический адрес в вашем JSON действительно предназначен как массив или как объект? Потому что в вашем примере это похоже на массив. Но я задаю этот вопрос, чтобы я, мы могли определить, что правильно делать для достижения вашей цели.
Ответ №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
будет класс, содержащий свойства Address
и PostCode
. Затем, когда запрос получен, сопоставьте модель запроса с моделью, необходимой вашему приложению. В mapper вы можете назначить соответствующий тип адреса, т.Е.
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:
Я создаю немного сложный случай для анализа этого json с помощью JsonConverter. И это работает для ваших требований.
Основная функция используется 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();
}
}