question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

JsonContainerAttribute Does Not Respect NamingStrategyParameters for Dictionaries

See original GitHub issue

Source/destination types

[JsonObject(NamingStrategyType = typeof(SnakeCaseNamingStrategy),
            NamingStrategyParameters = new object[] { true, true })]
public class UsesOverriddenNamingStrategy
{
    public int Id { get; set; }
    public string FullName { get; set; }
    public IDictionary<string, int> ExtraThings { get; set; }
}

Source/destination JSON

// actual value:
{"id":42,"full_name":"John Doe","extra_things":{"ExtraValue":1}}

// expected value:
{"id":42,"full_name":"John Doe","extra_things":{"extra_value":1}}

Steps to reproduce

var foo = new UsesOverriddenNamingStrategy
{
    Id = 42,
    FullName = "John Doe",
    ExtraThings = new Dictionary<string, int>
    {
        ["ExtraValue"] = 1
    }
}

string json = JsonConvert.SerializeObject(foo);

Expected behavior

I expected the dictionary keys to be converted to snake case because the NamingStrategyParameters were true (i.e. ProcessDictionaryKeys == true).

Actual behavior

The property names were overridden (so NamingStrategyType was used) but dictionary keys were not converted. They use the naming strategy from the default contract resolver instead of the one specified in either the JsonObject or JsonProperty override.

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:1
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

3reactions
adamrodgercommented, Oct 23, 2019

That’s fine and all, but then that probably means that [JsonProperty] shouldn’t allow specifying NamingStrategyParameters if they aren’t actually going to be used. This is misleading:

public class Foo
{
    [JsonProperty(
      NamingStrategyType = typeof(CamelCaseNamingStrategy), // <-- this will be used
      NamingStrategyParameters = new object[] { true, true })] // <-- but these won't
    public IDictionary<string, int> Bar { get; set; }
}

In that example, the first of those NamingStrategyParameters is specifically related to the handling of dictionary keys, and it’s applied to a dictionary, and yet they aren’t used. That doesn’t really follow the Principle of Least Surprise.

I’ve added a PR which allows those parameters to be bound to the property so that they will be used during serialization.

You could implement your own class MyDictionary : IDictionary<string, int> and decorate it with [JsonDictionary] to control this behaviour, but then that means you’re using different types to influence serialisation settings whereas typically you use [JsonProperty] to influence those regardless of type.

3reactions
JamesNKcommented, Oct 23, 2019

Applying a naming strategy to a type doesn’t automatically make all its child objects also use that strategy. In this case ExtraThings is a child object.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to make Json Serialize ignore dictionary keys
I'm trying to serialize a dictionary within a class and the keys inside the CustomAttributes dictionary are getting formatted even though I've ...
Read more >
JsonContainerAttribute.NamingStrategyParameters Property
The parameter list to use when constructing the NamingStrategy described by NamingStrategyType. If null, the default constructor is used.
Read more >
Feature Request - JsonUtility can't serialize Dictionary
The simple answer is that JsonUtility uses the same serialization mechanism as the rest of Unity (the same one used for serializing asset...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found