获取JsonConvert.DeserializeObject的动态对象,使属性大写

时间:2016-03-03 16:23:00

标签: c# json json.net

我不确定如何寻求帮助,这有点不寻常,我同意,所以请原谅我。我将尝试解释如下:

•我使用POST消费JSON并获取动态对象。我需要将动态对象中的所有传入属性转换为大写。

•我使用的是 我认为 是一个有效的解决方案。我将JSON转换为字符串Dictionary,然后在将Key转换为Key.ToUpper()之后将值放入新字典中,然后将其反序列化为动态对象。

当前工作解决方案如下:

string _StrJSON = @"{""FIELDA"" : ""1234"",""fieldb"" : ""OtherValue""}";

var d = JsonConvert.DeserializeObject<Dictionary<string, string>>(_StrJSON);

d.ContainsKey("FIELDB").Dump(); // returns false, obviously.

Dictionary<string, string> dr = new Dictionary<string, string>();

d.ToList().ForEach(r => dr.Add(r.Key.ToUpper(), r.Value));

dr.Dump("dr"); // FIELDA 1234  - FIELDB OtherValue 

var a  = JsonConvert.SerializeObject(dr);
a.Dump(); // {"FIELDA":"1234","FIELDB":"OtherValue"}

这很有效。

[编辑] 关于我的&#34; var&#34;以上和其他东西。我非常清楚什么是动态的,什么是不动的。 [/编辑]

到目前为止我所尝试的不工作如下:

namespace Newtonsoft.Json
{
/// <summary>
/// Converts JSON keys to uppercase.
/// </summary>
public class UppercaseContractResolver : Serialization.DefaultContractResolver
{
    #region Methods.

    #region Public Methods.

    /// <summary>
    /// Resolves property name for this JSON object.
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    protected override string ResolvePropertyName(string key)
    {
        return key.ToUpper();
    }

    #endregion

    #endregion

    #region Constructors.

    /// <summary>
    /// Converts JSON keys to uppercase.
    /// </summary>
    public UppercaseContractResolver()
    {
    }

    #endregion
}

/// <summary>
/// Wrapper for Newtonsoft.Json.JsonConvert for JSON keys as uppercase.
/// </summary>
public static class JsonConvertUpper
{
    #region Members.        
    #endregion

    #region Methods.

    #region Public Methods.

    /// <summary>
    /// Tries to serialize specified object with JSON keys in upper case.
    /// <para>e.g. "key":value should become "KEY":value by using this method.</para>
    /// </summary>
    /// <param name="value">Object.</param>
    /// <returns></returns>
    public static string SerializeObjectUpper(object value)
    {
        return JsonConvert.SerializeObject(value, new JsonSerializerSettings
        {
            ContractResolver = new UppercaseContractResolver()
        });
    }

    /// <summary>
    /// Tries to Deserialize specified object with JSON keys in upper case.
    /// <para>e.g. "key":value should become "KEY":value by using this method.</para>
    /// </summary>
    /// <param name="strValue">String.</param>
    /// <returns></returns>
    public static object DeserializeObjectUpper(string strValue)
    {
        // DeserializeObject does not allow uppercase properties. So use SerializeObjectUpper and then deserialize.

        var value = JsonConvert.DeserializeObject(strValue);

        string strJSON = SerializeObjectUpper(value);

        return JsonConvert.DeserializeObject(strJSON, new JsonSerializerSettings()
        {
            ContractResolver = new UppercaseContractResolver()
        });
    }

    #endregion

    #endregion
}
}

上面的方法调用是:

  dynamic json = JsonConvertUpper.DeserializeObjectUpper(_StrJSON);

                if (json.CTN== null)
                {...}

[编辑] 请注意我没有类,因为JSON键必须被视为UPPERCASE,类和其他代码等都在ProperCase中。 [/编辑]

任何方式 内部 JsonConvert都可以吗?为了避免我的手动补丁?任何帮助表示赞赏。感谢。

1 个答案:

答案 0 :(得分:1)

您的合同解析程序不起作用的原因是Json.NET的contract resolver定义了如何在序列化时将JSON映射到POCO的属性 - 但是当您反序列化为dynamic时, Json.NET实际上并不是从POCO映射到POCO,而是直接从JSON构建JToken层次结构,其成员implement IDynamicMetaObjectProvider。即。

dynamic o = JsonConvert.DeserializeObject(strJSON);

dynamic o = JToken.Parse(strJSON);

是一样的。

鉴于这种情况,最简单的方法是在构建层次结构时将每个属性名称显式转换为大写,如下所示:

public static class JsonExtensions
{
    public static JToken ParseUppercase(string json)
    {
        using (var textReader = new StringReader(json))
        using (var jsonReader = new JsonTextReader(textReader))
        {
            return jsonReader.ParseUppercase();
        }
    }

    public static JToken ParseUppercase(this JsonReader reader)
    {
        return reader.Parse(n => n.ToUpperInvariant());
    }

    public static JToken Parse(this JsonReader reader, Func<string, string> nameMap)
    {
        JToken token;
        using (var writer = new RenamingJTokenWriter(nameMap))
        {
            writer.WriteToken(reader);
            token = writer.Token;
        }

        return token;
    }
}

class RenamingJTokenWriter : JTokenWriter
{
    readonly Func<string, string> nameMap;

    public RenamingJTokenWriter(Func<string, string> nameMap)
        : base()
    {
        if (nameMap == null)
            throw new ArgumentNullException();
        this.nameMap = nameMap;
    }

    public override void WritePropertyName(string name)
    {
        base.WritePropertyName(nameMap(name));
    }

    // No need to override WritePropertyName(string name, bool escape) since it calls WritePropertyName(string name)
}

然后使用它:

dynamic json = JsonExtensions.ParseUppercase(_StrJSON);

示例fiddle