Случай верблюда по умолчанию имен свойств в сериализации 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());
}
Другие вопросы по тегам