Dapatkan objek dinamis untuk properti JsonConvert.DeserializeObject yang membuat huruf besar

Saya tidak yakin bagaimana cara mencari bantuan dan ini agak tidak biasa. Saya setuju, jadi mohon maaf. Saya akan mencoba menjelaskannya seperti di bawah ini:

• Saya menggunakan JSON menggunakan POST dan mendapatkan objek dinamis. Saya perlu mengonversi semua properti yang masuk dalam objek dinamis menjadi huruf besar.

• Saya menggunakan apa yang menurut saya merupakan solusi yang pasti. Saya mengonversi JSON ke Kamus string, lalu memasukkan nilai ke dalam kamus baru setelah mengonversi Kunci menjadi Key.ToUpper() dan kemudian membatalkan serialisasinya kembali menjadi objek dinamis.

Solusi yang berfungsi saat ini adalah sebagai berikut:

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"}

Ini bekerja.

[EDIT] Beberapa kebingungan tentang "var" saya di atas dan hal lainnya. Saya sangat jelas tentang apa yang dinamis dan apa yang tidak. [/EDIT]

Yang sudah saya coba sejauh ini yang TIDAK BEKERJA adalah seperti di bawah ini:

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
}
}

Panggilan metode di atas adalah:

  dynamic json = JsonConvertUpper.DeserializeObjectUpper(_StrJSON);

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

[EDIT] Harap diperhatikan bahwa saya tidak memiliki kelas karena kunci JSON harus diperlakukan sebagai UPPERCASE dan kelas serta kode lain dll semuanya ada di ProperCase. [/EDIT]

Adakah cara untuk melakukannya di dalam JsonConvert? Untuk menghindari patch manual saya? Bantuan apa pun dihargai. Terima kasih.


person Fawad Raza    schedule 03.03.2016    source sumber
comment
Anda dapat mengganti nama props menggunakan atribut JsonProperty di kelas Anda   -  person Ňɏssa Pøngjǣrdenlarp    schedule 03.03.2016
comment
Harap diingat bahwa objek dinamis adalah objek yang ditentukan saat runtime. Ini bukan tipe dinamis. Variabel var adalah variabel yang diketik dengan kuat. Hanya ingin menghapus terminologi ini di sini   -  person misha130    schedule 03.03.2016
comment
Ya, saya tahu, tetapi saya telah mengedit pertanyaan saya.   -  person Fawad Raza    schedule 03.03.2016


Jawaban (1)


Alasan penyelesai kontrak Anda tidak berfungsi adalah penyelesai kontrak mendefinisikan cara memetakan JSON dari dan ke properti POCO saat membuat serial -- namun saat Anda melakukan deserialisasi ke dynamic, Json.NET sebenarnya tidak memetakan dari dan ke POCO, melainkan membangun JToken hierarki langsung dari JSON, yang anggotanya implementasi IDynamicMetaObjectProvider. Yaitu.

dynamic o = JsonConvert.DeserializeObject(strJSON);

Dan

dynamic o = JToken.Parse(strJSON);

adalah sama.

Mengingat hal ini terjadi, cara termudah untuk melakukan apa yang Anda inginkan adalah dengan secara eksplisit mengonversi setiap nama properti menjadi huruf besar saat hierarki sedang dibuat, seperti:

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)
}

Dan kemudian menggunakannya seperti:

dynamic json = JsonExtensions.ParseUppercase(_StrJSON);

Contoh biola.

person dbc    schedule 03.03.2016
comment
Ah @dbc benar-benar cantik! Terima kasih banyak. :) - person Fawad Raza; 04.03.2016
comment
Saya mencoba dengan JToken dan JArray pagi ini dengan semua jenis loop, untuk array di dalam objek. Saya menguji biola dengan string _StrJSON = @"{""FIELDA"" : ""1234"",""fieldb"" : ""OtherValue"", ""ARRAYDATA"": [ {""FIELD1"":""ArrayPropOne"", ""ArrayInsideArray1"": [ {""Fieldx"":""InsideArray1"", ""ArrayInsideArray2"": [ {""Fieldxy"":""InsideArray2""} ] } ]} ] }"; Berfungsi dengan baik. Terima kasih banyak untuk ini, sangat dihargai. - person Fawad Raza; 04.03.2016