How to serialize a JObject the same way as an object with Json.NET?

前端 未结 3 1824
一整个雨季
一整个雨季 2021-01-11 19:24

How do I control the serialization of a JObject to string?

I have some APIs that return a JObject and I usually apply some changes and persist or return them. I want

相关标签:
3条回答
  • 2021-01-11 20:10

    A solution that well integrates with NewtonSoft framework is to provide a custom JObject converter that honours the NamingStrategy.

    JObject Custom Converter

    public class JObjectNamingStrategyConverter : JsonConverter<JObject> {
    
    private NamingStrategy NamingStrategy { get; }
    
    public JObjectNamingStrategyConverter (NamingStrategy strategy) {
        if (strategy == null) {
            throw new ArgumentNullException (nameof (strategy));
        }
        NamingStrategy = strategy;
    }
    
    public override void WriteJson (JsonWriter writer, JObject value, JsonSerializer serializer) {
        writer.WriteStartObject ();
        foreach (JProperty property in value.Properties ()) {
            var name = NamingStrategy.GetPropertyName (property.Name, false);
            writer.WritePropertyName (name);
            serializer.Serialize (writer, property.Value);
        }
        writer.WriteEndObject ();
    }
    
    public override JObject ReadJson (JsonReader reader, Type objectType, JObject existingValue, bool hasExistingValue, JsonSerializer serializer) {
        throw new NotImplementedException ();
    }
    }
    

    Usage

    var snakeNameStrategy = new SnakeCaseNamingStrategy ();
    var jsonSnakeSettings = new JsonSerializerSettings {
    Formatting = Formatting.Indented,
    Converters = new [] { new JObjectNamingStrategyConverter (snakeNameStrategy) },
       ContractResolver = new DefaultContractResolver {
           NamingStrategy = snakeNameStrategy
       },
    };
    
    var json = JsonConvert.SerializeObject (obj, jsonSnakeSettings);
    

    You can find a working PoC on GitHub.

    0 讨论(0)
  • 2021-01-11 20:15

    The only way I was able to do this is by first converting the JObject to a string, then deserializing that string into an ExpandoObject (don't deserialize to object because you'll get back a JObject). The ExpandoObject is like a dictionary, which will cause JsonConvert to actually invoke the configured name case strategy. I'm not sure why the author of Newtonsoft.Json didn't handle JObject types the same way as they seem to be doing for dictionary types, but at least this work around works.

    Example:

    // Construct a JObject.
    var jObject = JObject.Parse("{ SomeName: \"Some value\" }");
    
    // Deserialize the object into an ExpandoObject (don't use object, because you will get a JObject).
    var payload = JsonConvert.DeserializeObject<ExpandoObject>(jObject.ToString());
    
    // Now you can serialize the object using any serializer settings you like.
    var json = JsonConvert.SerializeObject(payload, new JsonSerializerSettings
    {
        ContractResolver = new DefaultContractResolver
        {
            NamingStrategy = new CamelCaseNamingStrategy
            {
                // Important! Make sure to set this to true, since an ExpandoObject is like a dictionary.
                ProcessDictionaryKeys = true,
            }
        }
    }
    );
    
    Console.WriteLine(json); // Outputs: {"someName":"Some value"}
    

    I picked-up the trick with the ExpandoObject here: JObject & CamelCase conversion with JSON.Net

    0 讨论(0)
  • 2021-01-11 20:24

    When a JObject is serialized its raw JSON is written. JsonSerializerSettings do not effect its written JSON.

    0 讨论(0)
提交回复
热议问题