Fix key camel case#2177
Conversation
| /// </summary> | ||
| /// <param name="keyBeUpperCamel"></param> | ||
| /// <returns></returns> | ||
| internal static string ToLowerCamel(string keyBeUpperCamel) |
There was a problem hiding this comment.
Newtonsoft.Json's camelCase conversion function is far more complicated than this. I don't know why. Maybe it transforms _ThisHere to _thisHere as well. As whatever this function does will be locked in for schema compatibility reasons, we should be mindful about the various prior art in this area and be sure we are comfortable with the design.
There was a problem hiding this comment.
[MessagePackObject]
public class Test {
public string Name { get; set; }
public int Age { get; set; }
public string FullName { get; set; }
}
IF [MessagePackObject(keyAsPropertyName = true,keyNameCamelCase =true)]
The current Keys are: name,age,fullName
ELSE IF [MessagePackObject(keyAsPropertyName = true)]
The current Keys are: Name,Age,FullName
ELSE [MessagePackObject(keyNameCamelCase =true)]
The current Keys are: name,age,fullName
| /// <param name="keyNameCamelCase"> | ||
| /// set keyNameCamelCase=true Convert string type Key to CamelCase rule. | ||
| /// </param> | ||
| public MessagePackObjectAttribute(bool keyAsPropertyName, bool keyNameCamelCase) |
There was a problem hiding this comment.
Thank you for reverting the change to the existing constructor.
I wonder if we need this constructor though. It will require folks to pass in [MessagePackObject(true, true)] to get to the camel case setting. But if you omit this constructor, this syntax is (still) available which IMO reads better:
[MessagePackObject(KeyNameCamelCase = true)]
There was a problem hiding this comment.
Or, if you take my suggestion about enums, a new constructor would work that would be even simpler:
[MessagePackObject(KeyPolicy.CamelCasePropertyNames)]There was a problem hiding this comment.
Thanks. Not quite what I was thinking of, but I pushed a change to show my intent.
There was a problem hiding this comment.
This is acceptable for dynamic resolver generation at this point. Thanks.
The remaining work is to:
- ensure the new policy is honored by the source generator path as well.
- add tests for the new option, for both serialization paths source generation and dynamic object resolver.
AArnott
left a comment
There was a problem hiding this comment.
Your latest iteration has some good changes. Thank you.
We still need the source generation side to update to support the new property name transformation.
| // {"Foo":10} | ||
| Console.WriteLine(MessagePackSerializer.SerializeToJson(new Sample3 { Foo = 10, Bar = 20 })); | ||
|
|
||
| // {"foo":10,"bar":20} |
There was a problem hiding this comment.
This would make a more informative sample if the property names were multiple words long, so that those not familiar with camel case can readily see that only the first letter is lowercase and the rest are left alone.
| /// Gets a value indicating whether to automatically serialize all internal and public fields and properties using their property name as the key in a map. | ||
| /// </summary> | ||
| [Obsolete($"Use {nameof(KeyPolicy)} instead.")] | ||
| public bool KeyAsPropertyName { get; } |
There was a problem hiding this comment.
Nope, can't do that. Removing a public property is a breaking change. That's why I added the Obsolete attribute instead of removing it.
What we could do though, is replace it with something that doesn't need to be set in the constructor, like this:
[Obsolete($"Use {nameof(KeyPolicy)} instead.")]
public bool KeyAsPropertyName => this.KeyPolicy is KeyPolicy.ImplicitPropertyNames or KeyPolicy.ImplicitCamelCasePropertyNames;There was a problem hiding this comment.
I think KeyAsPeopleName can be cleaned up before merging the main code.
Using Obsolvete will make the code more chaotic, and concise code will make it clearer to understand.
There was a problem hiding this comment.
You seem to think this is up for debate. It is not. Breaking changes are unacceptable in a stable library such as this one. The property must remain. The only question is whether to add the [Obsolete] attribute to it. In this case I believe it should, because it is both redundant with the new property and somewhat hazardous for anyone depending on it since it no longer is guaranteed to mean what it used to as a 3rd mode has been added.
And considering almost no one is ever reading this property outside of this library, adding Obsolete to it is unlikely to upset anyone.
| public const int Prop1Constant = 102; | ||
| public const int Prop2Constant = 2223; | ||
|
|
||
| public int Prop1 { get; set; } = Prop1Constant; |
There was a problem hiding this comment.
Thanks for the tests. They'll be more useful if the property names had multiple uppercase letters in them so that we can verify that only the first letter is changed.
Add KeyName CamelCase