我有一个与另一个API对话的API。 响应模型如下所示:
public class AddressResponseModel
{
public string Id { get; set; }
public string SaveAs { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Phone { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string County { get; set; }
public string Country { get; set; }
public string PostCode { get; set; }
}
所以,我需要将它发送到另一个API。我真的不想在JavaScript中使用响应,我只想将它发送到我的端点并让服务器处理它的分解。 所以,我试着这样做:
public class AddressBindingModel
{
[Required]
[JsonProperty("address_1")]
public string Address1 { get; set; }
[JsonProperty("address_2")]
public string Address2 { get; set; }
[Required]
[JsonProperty("city")]
public string City { get; set; }
[Required]
[JsonProperty("county")]
public string County { get; set; }
[Required]
[JsonProperty("postcode")]
public string PostCode { get; set; }
[Required]
[JsonProperty("country")]
public string Country { get; set; }
[JsonProperty("save_as")]
public string SaveAs { get; set; }
}
但问题是它希望json遵循相同的属性格式。 如何让它期望我的未修改的响应模型,但输出带有下划线的JSON?
为了澄清,我将发布我的模型:
{
address1: '123',
address2: 'Some street',
city: 'London',
county: 'London',
country: 'GB',
saveAs: 'Home'
}
然后我的API会将此信息发送到另一个API:
{
address_1: '123',
address_2: 'Some street',
city: 'London',
county: 'London',
country: 'GB',
save_as: 'Home'
}
答案 0 :(得分:0)
如果您想使用相同的类自动生成具有不同属性名称的JSON,而不必为每个属性名称编写自定义JsonConverter
,那么您将需要创建自己的{{3例如:
Json.NET提供custom ContractResolver
。
CamelCasePropertyNamesContractResolver
有一个原型PascalCaseToUnderscoreContractResolver
。
如果您有一种确定的方法将所有.Net属性名称映射到给定使用上下文(post或get-from-api)的相应属性名称,您可以创建一个像上面的一个合同解析器。
但是,如果没有为JSON属性名映射.Net属性名称的一般规则,并且每个上下文可能需要一些每个属性的自定义,您可以创建自己的ContractResolver
适用于特定的命名上下文,以及您自己的System.Attribute
,它提供在此上下文中使用的JSON上下文名称和属性名称。即:
[System.AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true, Inherited = true)]
public class JsonConditionalNameAttribute : System.Attribute
{
readonly string contextName;
readonly string propertyName;
public string ContextName { get { return contextName; } }
public string PropertyName { get { return propertyName; } }
public JsonConditionalNameAttribute(string contextName, string propertyName)
{
this.contextName = contextName;
this.propertyName = propertyName;
}
}
public class ConditionalNameContractResolver : DefaultContractResolver
{
readonly string contextName;
public string ContextName { get { return contextName; } }
public ConditionalNameContractResolver(string contextName)
: base()
{
if (string.IsNullOrEmpty(contextName))
throw new ArgumentNullException();
if (string.IsNullOrEmpty(contextName))
throw new ArgumentException();
this.contextName = contextName;
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var jProperty = base.CreateProperty(member, memberSerialization);
var attrs = jProperty.AttributeProvider.GetAttributes(typeof(JsonConditionalNameAttribute), true)
.Cast<JsonConditionalNameAttribute>()
.Where(a => a.ContextName == ContextName)
.Select(a => a.PropertyName)
.Distinct()
.ToList();
if (attrs.Count == 1)
{
jProperty.PropertyName = attrs[0];
}
else if (attrs.Count > 1)
{
throw new JsonSerializationException(string.Format("Multiple conditional property attributes found for \"{0}\" in in context \"{1}\": \"{2}\"", jProperty, contextName, String.Join(",", attrs)));
}
return jProperty;
}
}
然后你的绑定模型看起来像:
public static class AddressBindingModelContexts
{
public const string Post = "post";
public const string GetFromApi = "getFromApi";
}
public class AddressBindingModel
{
[JsonConditionalName(AddressBindingModelContexts.GetFromApi, "address_1")]
[JsonConditionalName(AddressBindingModelContexts.Post, "address1")]
public string Address1 { get; set; }
[JsonConditionalName(AddressBindingModelContexts.GetFromApi, "address_2")]
[JsonConditionalName(AddressBindingModelContexts.Post, "address2")]
public string Address2 { get; set; }
[JsonProperty("city")]
public string City { get; set; }
[JsonProperty("county")]
public string County { get; set; }
[JsonProperty("postcode")]
public string PostCode { get; set; }
[JsonProperty("country")]
public string Country { get; set; }
[JsonConditionalName(AddressBindingModelContexts.GetFromApi, "save_as")]
[JsonConditionalName(AddressBindingModelContexts.Post, "saveAs")]
public string SaveAs { get; set; }
}
测试:
var jsonFromApi = GetJsonFromApi();
var postContract = new ConditionalNameContractResolver(AddressBindingModelContexts.Post);
var getFromApiContract = new ConditionalNameContractResolver(AddressBindingModelContexts.GetFromApi);
var model = JsonConvert.DeserializeObject<AddressBindingModel>(jsonFromApi, new JsonSerializerSettings { ContractResolver = getFromApiContract });
var postJson = JsonConvert.SerializeObject(model, Formatting.Indented, new JsonSerializerSettings { ContractResolver = postContract });
Debug.WriteLine(postJson); // Verify the postJson has the necessary properties and data.
要更改从Web API返回的所有结果的合约解析程序,请参阅This Answer。要在返回特定Web Api调用的结果时使用自定义合约解析程序,请参阅JSON and XML Serialization in ASP.NET Web API: Camel Casing。