Случай верблюда по умолчанию имен свойств в сериализации JSON
У меня есть несколько классов, которые в какой-то момент будут сериализованы в JSON, и для того, чтобы следовать обоим соглашениям C# для внутреннего интерфейса и соглашениям JavaScript во внешнем интерфейсе, я определял свойства, подобные этому:
[JsonProperty(PropertyName="myFoo")]
public int MyFoo { get; set; }
Так что в C# я могу:
MyFoo = 10;
И в Javascript я могу:
if (myFoo === 10)
Но делать это для каждой собственности утомительно. Есть ли быстрый и простой способ установить способ по умолчанию, который JSON.Net обрабатывает имена свойств, так что он автоматически верблюжий, если не указано иное?
8 ответов
Вы можете использовать предоставленный класс http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Serialization_CamelCasePropertyNamesContractResolver.htm:
var serializer = new JsonSerializer
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
var jobj = JObject.FromObject(request, serializer);
Другими словами, вам не нужно создавать собственный распознаватель самостоятельно.
При сериализации вашего объекта, передайте некоторые пользовательские настройки.
var settings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
var json = JsonConvert.SerializeObject(yourObject, settings);
Лучше использовать новый CamelCaseNamingStrategy
:
new JsonSerializerSettings()
{
ContractResolver = new new DefaultContractResolver
{
NamingStrategy = new CamelCaseNamingStrategy()
}
};
Он не переопределяет пользовательские имена, установленные JsonPropert('Name')
по умолчанию. (Вы можете изменить поведение CamelCaseNamingStrategy(bool, bool)
ctor.) Итак, не нужно создавать пользовательский класс, как ответ @Matt Burland.
JObject.FromObject
использует настройки по умолчанию из JsonConvert
по умолчанию. Есть свойство func, которое вы можете назначить так:
JsonConvert.DefaultSettings = () => new JsonSerializerSettings()
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
и всякий раз, когда вы звоните Jobject.FromObject
, он будет использовать эту функцию для создания настроек.
Поскольку принятый ответ только для ссылок, я добавляю фактический код, который я использовал (в случае, если ссылка умирает). Это в значительной степени то же самое, что было в ссылке:
// Automatic camel casing because I'm bored of putting [JsonProperty] on everything
// See: http://harald-muehlhoff.de/post/2013/05/10/Automatic-camelCase-naming-with-JsonNET-and-Microsoft-Web-API.aspx#.Uv43fvldWCl
public class CamelCase : CamelCasePropertyNamesContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member,
MemberSerialization memberSerialization)
{
var res = base.CreateProperty(member, memberSerialization);
var attrs = member.GetCustomAttributes(typeof(JsonPropertyAttribute), true);
if (attrs.Any())
{
var attr = (attrs[0] as JsonPropertyAttribute);
if (res.PropertyName != null && attr.PropertyName != null)
res.PropertyName = attr.PropertyName;
}
return res;
}
}
Единственное изменение, которое я сделал, было добавление attr.PropertyName != null
к предложению if из-за случая, когда я добавил что-то вроде:
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string SomeProperty { get; set; }
И не хотел указывать PropertyName
(так что это ноль). Выше будет сериализовано в JSON как someProperty
,
Вы можете использовать пользовательский определитель контрактов:
class MyContractResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var properties = base.CreateProperties(type, memberSerialization);
foreach (var property in properties)
{
property.PropertyName = char.ToLower(property.PropertyName[0]) + string.Join("", property.PropertyName.Skip(1));
}
return properties;
}
}
И используйте это как:
class MyClass
{
public int MyProperty { get; set; }
public int MyProperty2 { get; set; }
}
var json = JsonConvert.SerializeObject(new MyClass(),
Formatting.Indented,
new JsonSerializerSettings { ContractResolver = new MyContractResolver() });
В .NET 5.0 вы можете использовать System.Text.Json и указать ProperyNamingPolicy внутри JsonSerializerOptions.
System.Text.Json.JsonSerializerOptions.PropertyNamingPolicy
Вот ссылка на страницу документов Microsoft по настройке свойства для использования верблюжьего регистра.
var serializeOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, serializeOptions);
Учебный класс
public class WeatherForecastWithPropertyNameAttribute
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string Summary { get; set; }
[JsonPropertyName("Wind")]
public int WindSpeed { get; set; }
}
Вывод JSON
{
"date": "2019-08-01T00:00:00-07:00",
"temperatureCelsius": 25,
"summary": "Hot",
"Wind": 35
}
public static JsonSerializer FormattingData()
{
var jsonSerializersettings = new JsonSerializer {
ContractResolver = new CamelCasePropertyNamesContractResolver() };
return jsonSerializersettings;
}
public static JObject CamelCaseData(JObject jObject)
{
var expandoConverter = new ExpandoObjectConverter();
dynamic camelCaseData =
JsonConvert.DeserializeObject(jObject.ToString(),
expandoConverter);
return JObject.FromObject(camelCaseData, FormattingData());
}