我有一个.Net Core Web API。当模型属性与请求主体匹配时,它会自动映射模型。例如,如果您有这个类:
public class Package
{
public string Carrier { get; set; }
public string TrackingNumber { get; set; }
}
如果请求主体是以下JSON,它会正确地将它绑定到POST端点:
{
carrier: "fedex",
trackingNumber: "123123123"
}
我需要做的是指定要映射的自定义属性。例如,使用上面的同一个类,如果TrackingNumber以tracking_number
的形式出现,我需要能够映射到JSON。
我该怎么做?
答案 0 :(得分:14)
更改您的包类并为您希望映射到不同json字段的每个字段添加JsonProperty装饰。
public class Package
{
[JsonProperty(PropertyName = "carrier")]
public string Carrier { get; set; }
[JsonProperty(PropertyName = "trackingNumber")]
public string TrackingNumber { get; set; }
}
答案 1 :(得分:7)
默认情况下,
从3.0开始,ASP.NET Core Json.NET(Newtonsoft.Json)子组件从ASP.NET Core共享框架中删除。宣布:“ Json.NET将继续与ASP.NET Core一起使用,但在共享框架中将不会出现。”新添加的Json Api声称专门针对高性能方案。
使用JsonPropertyName
属性设置自定义属性名称:
using System.Text.Json.Serialization;
public class Package
{
[JsonPropertyName("carrier")]
public string Carrier { get; set; }
[JsonPropertyName("tracking_number")]
public string TrackingNumber { get; set; }
}
希望有帮助!
答案 2 :(得分:6)
我认为这也应该起作用:
using Microsoft.AspNetCore.Mvc;
public class Package
{
[BindProperty(Name ="carrier")]
public string Carrier { get; set; }
[BindProperty(Name ="trackingNumber")]
public string TrackingNumber { get; set; }
}
答案 3 :(得分:0)
通过使用自定义转换器,您将能够实现所需 基于属性的以下组件套件可能适合您的需求,并且在您想要扩展它时非常通用。
基本属性类
定义IsMatch
,它允许您定义对象属性是否与json属性匹配。
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]
public abstract class JsonDeserializationPropertyMatchAttribute : Attribute
{
protected JsonDeserializationPropertyMatchAttribute() { }
public abstract bool IsMatch(JProperty jsonProperty);
}
示例实现:多个反序列化名称
定义一个属性,允许您将多个名称与属性相关联。 IsMatch
实现只是循环遍历它们并尝试查找匹配。
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]
public class JsonDeserializationNameAttribute : JsonDeserializationPropertyNameMatchAttribute
{
public string[] PropertyNames { get; private set; }
public JsonDeserializationNameAttribute(params string[] propertyNames)
{
this.PropertyNames = propertyNames;
}
public override bool IsMatch(JProperty jsonProperty)
{
return PropertyNames.Any(x => String.Equals(x, jsonProperty.Name, StringComparison.InvariantCultureIgnoreCase));
}
}
转换器为了将这两个属性绑定到json反序列化,需要以下转换器:
public class JsonDeserializationPropertyMatchConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType.IsClass;
}
public override bool CanWrite
{
get
{
return false;
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var constructor = objectType.GetConstructor(new Type[0]);
if (constructor == null)
throw new JsonSerializationException("A parameterless constructor is expected.");
var value = constructor.Invoke(null);
var jsonObject = JObject.Load(reader);
var jsonObjectProperties = jsonObject.Properties();
PropertyInfo[] typeProperties = objectType.GetProperties();
var typePropertyTuples = new List<Tuple<PropertyInfo, Func<JProperty, bool>>>();
foreach (var property in typeProperties.Where(x => x.CanWrite))
{
var attribute = property.GetCustomAttribute<JsonDeserializationPropertyMatchAttribute>(true);
if (attribute != null)
typePropertyTuples.Add(new Tuple<PropertyInfo, Func<JProperty, bool>>(property, attribute.IsMatch));
else
typePropertyTuples.Add(new Tuple<PropertyInfo, Func<JProperty, bool>>(property, (x) => false));
}
foreach (JProperty jsonProperty in jsonObject.Properties())
{
var propertyTuple = typePropertyTuples.FirstOrDefault(x => String.Equals(jsonProperty.Name, x.Item1.Name, StringComparison.InvariantCultureIgnoreCase) || x.Item2(jsonProperty));
if (propertyTuple != null)
propertyTuple.Item1.SetValue(value, jsonProperty.Value.ToObject(propertyTuple.Item1.PropertyType, serializer));
}
return value;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
示例使用上面粘贴的代码,并按照以下方式修改类,我设法让对象正确反序列化:
[JsonConverter(typeof(JsonDeserializationPropertyMatchConverter))]
public class Package
{
public string Carrier { get; set; }
[JsonDeserializationName("Tracking_Number","anotherName")]
public string TrackingNumber { get; set; }
}
输出1
var input = "{ carrier: \"fedex\", trackingNumber: \"123123123\" }";
var output = JsonConvert.DeserializeObject<Package>(input); // output.TrackingNumber is "123123123"
输出2
var input = "{ carrier: \"fedex\", tracking_Number: \"123123123\" }";
var output = JsonConvert.DeserializeObject<Package>(input); // output.TrackingNumber is "123123123"
输出3
var input = "{ carrier: \"fedex\", anotherName: \"123123123\" }";
var output = JsonConvert.DeserializeObject<Package>(input); // output.TrackingNumber is "123123123"
答案 4 :(得分:0)
就我而言,我不想更改属性名称Carrier
和TrackingNumber
所以我只需在JsonResult响应上添加new JsonSerializerSettings()
public JsonResult GetJQXGridData(){
var Data = .......
return Json(Data, new JsonSerializerSettings()) //change here
}
不使用JsonSerializerSettings
输出
{
carrier: "fedex",
trackingNumber: "123123123"
}
使用JsonSerializerSettings
输出
{
Carrier: "fedex",
TrackingNumber: "123123123"
}
答案 5 :(得分:0)
对于DotnetCore3.1,我们可以使用
public class Package
{
[JsonProperty("carrier")]
public string Carrier { get; set; }
[JsonProperty("trackingNumber")]
public string TrackingNumber { get; set; }
}
答案 6 :(得分:0)
如果您使用XML序列化(ContentTypes.TextXml),则可以使用属性
[XmlElement(ElementName = "name")]
更改字段名称。通过使用命名空间System.Xml.Serialization。
我尝试了[JsonProperty("name")]
和[System.Runtime.Serialization.DataMember(Name = "name")]
,但对于我的XML内容,它们不起作用。
答案 7 :(得分:0)
出于某种原因,以下在我的模型类中对我不起作用:
[JsonPropertyName("carrier")]
public string Carrier { get; set; }
虽然这有效:
[JsonProperty(PropertyName = "carrier")]
public string Carrier { get; set; }
一个来自 system.text.Json 库,另一个来自 Newtonsoft.json 但我真的很想知道为什么会这样。因为我试图在 API 调用中返回 Json 字符串中的属性值。