4

I am serializing an object of this format using Newtonsoft.JSON:

class Message
{
    public HeaderType Header { get; set; }
    public object Body { get; set; }
}

I want to turn the Header and Body properties into camel case, while presevering the case of the properties of the thing assigned to Body.

So if the message looks like:

var result = new Message() { Header = myHeader, Body = new SomeClass() { A = 1 }});

I want the output to look like:

{ header = myHeader, body = { A = 1 } } // I realize this isn't valid C#

Right now, I'm doing this to get the camel case conversion, but of course it's affecting everything.

string stringRepresentationOfObj = JsonConvert.SerializeObject(obj, new JsonSerializerSettings {
    ContractResolver = new DefaultContractResolver {
        NamingStrategy = new CamelCaseNamingStrategy()
    }
});

Is there a way to ignore certain parts of the object? I see that the docs call out OverrideSpecifiedNames, ProcessDictionaryKeys, and ProcessExtensionDataNames, but it doesn't look like that's what I want.

Am I forced to use a some kind of custom naming strategy? How can I achieve this?

pushkin
  • 9,575
  • 15
  • 51
  • 95
  • You can configure a naming strategy as an attribute on the class as shown in [Issue with serializing data using JSON.Net](https://stackoverflow.com/a/40687963/3744182) (forces default) and [Configure Json.NET serialization settings on a class level](https://stackoverflow.com/a/44805815/3744182) (forces camel case). Is this what you want? – dbc May 03 '18 at 00:24

2 Answers2

6

You can configure a CamelCaseNamingStrategy to not camel case properties that already have a name specified with an attribute, Check documentation here

Specify property name as below

[JsonProperty(PropertyName = "Name")]
public string Name{ get; set; }

And in CamelCaseNamingStrategy set OverrideSpecifiedNames = false

string stringRepresentationOfObj = JsonConvert.SerializeObject(obj, new JsonSerializerSettings
{
    ContractResolver = new DefaultContractResolver
    {
        NamingStrategy = new CamelCaseNamingStrategy()
        {
            OverrideSpecifiedNames = false
        }
    }
});

Another way is to modify your type only using JsonObject attribute as below, this will force your type properties only to be in camelCase and any nested properties will not be affected.

[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]
public class ApiMessage
{
    public HeaderType Header { get; set; }

    public object Body { get; set; }
}

Also, add JsonObject attribute to HeaderType class

[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]
public class HeaderType
{
    public string MyPropertyA { get; set; }

    public string MyPropertyB { get; set; }
}

Your result should be as below

{
  "header": {
    "myPropertyA": "AAA",
    "myPropertyB": "BBB"
  },
  "body": {
    "ObjectPropertyA": "Value A",
    "ObjectPropertyB": "Value B",
    "ObjectPropertyC": "Value C"
  }
}
ElasticCode
  • 7,311
  • 2
  • 34
  • 45
  • 1
    `OverrideSpecifiedNames` is by default set to false. Second, I was looking for a solution where you don't have to attribute every property with `JsonProperty`. Imagine that the value of `Body` comes from god knows where, and I don't have access to it. I was looking for a more general solution where I could make *every* property inside `Body` not turn into camel case. – pushkin May 03 '18 at 22:42
  • Check this [JSON.NET custom contract resolvers library](https://github.com/ErikSchierboom/JsonDotNetCustomContractResolvers) Wildcards section – ElasticCode May 03 '18 at 23:01
  • From a glance, it doesn't look like that's what I want. It excludes all props *of a class*. In my case, I have a property named `Body`, and I want to exclude all of *its* properties. – pushkin May 04 '18 at 23:37
  • It looks like that attribute is applied to the whole class. I want everything to be camelcased except properties in `Body`. You changed `Header` to a string, but in my example it's not. It's an object, and I still want to camel case its properties. – pushkin May 05 '18 at 17:18
  • Yes, this will camelcased all properties except properties in `Body`, check updated answer for example – ElasticCode May 05 '18 at 21:54
  • 1
    This answer saved me and it is apparently rare, took way too long to find it after searching for NamingStrategy exclusions for an hour – Dagrooms Jun 06 '19 at 21:23
  • I'm looking for other way, where Body comes from somewhere which I don't have access and I still want to have camelCasing for everything. Any references on how to achieve this? By adding JsonObject, only the typed properties of the class are camelCased and not the inner objects. By adding at JSONSerialization, it resolves by problem. However, I need to support Pascal casing and camel casing for several scenarios. So, is there any way that could be configured at controller/class level to follow either Camelcasing / Pascal Casing? – Born2Code Sep 16 '21 at 18:58
1

You can create your own resolver to behave this way.

You'd create one, possibly have it look for a new attribute (which you'd create), that you can then use to decorate the properties you don't want camelCased.

mariocatch
  • 8,305
  • 8
  • 50
  • 71
  • I don't want *any* property on `Body` to be camel cased. I'd rather not force everyone to attribute their properties if I can help it. An example of this would help. – pushkin May 02 '18 at 22:16