öğesine dönüştür. Mümkün mü?'/> öğesine dönüştür. Mümkün mü?'/> öğesine dönüştür. Mümkün mü?'/> JObject'i <string, object> öğesine dönüştür. Mümkün mü? | tutuappapks.com

Soru JObject'i öğesine dönüştür. Mümkün mü?


İçine rasgele bir json yükünü kabul eden bir web API yöntemim var. JObject özelliği. Bu yüzden ne olduğunu bilmiyorum ama hala .NET türlerine çevirmem gerekiyor. Sahip olmak isterim Dictionary<string,object> Böylece istediğim gibi başa çıkabilirim.

Çok fazla arama yaptım, ancak hiçbir şey bulamadım ve bu dönüşümü yapmak için dağınık bir yöntem başlatmaya başladım. Bunu yapmanın kolay bir yolu var mı?

Giriş ->

JObject person = new JObject(
    new JProperty("Name", "John Smith"),
    new JProperty("BirthDate", new DateTime(1983, 3, 20)),
    new JProperty("Hobbies", new JArray("Play football", "Programming")),
    new JProperty("Extra", new JObject(
        new JProperty("Foo", 1),
        new JProperty("Bar", new JArray(1, 2, 3))
    )
)

Teşekkürler!


44
2018-02-15 00:58


Menşei


İki şey, JObject zaten Sözlük <string, JToken> uygular. Ve soru, alt özelliklerle uğraşmak için niyetiniz nedir? Sözlüğünüzdeki bu değer başka bir Sözlük <string,?> Olabilir mi? - Rich
Evet @Rich, alt özellikler başka bir Sözlük olacak <string, object> - tucaz
Ayrıca bakınız İç içe geçmiş / özyinelemeli Sözlük ve Listeye serileştirmek için JSON.NET'i nasıl kullanabilirim?. ToObject(JToken) İlk cevapta yardımcı yöntem, bu kodu minimum kod ile yapar. - Brian Rogers


Cevaplar:


Eğer varsa JObject nesneleri, aşağıdakiler işe yarayabilir:

JObject person;
var values = person.ToObject<Dictionary<string, object>>();

Eğer yoksa JObject ile bir tane oluşturabilirsiniz Newtonsoft.Json.Linq uzatma yöntemi:

using Newtonsoft.Json.Linq;

var values = JObject.FromObject(person).ToObject<Dictionary<string, object>>();

Aksi takdirde, bu cevap bir JSON dizesini bir Sözlük'e serpiştirirken sizi doğru yönde gösterebilir.

var values = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);

81
2018-02-15 01:12



+1, çünkü ilkel bir sözlüğünüz varsa, özellikle iyi çalışır. Örneğin, bu kod satırı benim için mükemmel çalıştı: Sözlük <string, decimal> feeChanges = dict.feeChanges.ToObject <Sözlük <string, decimal >> (); - allen1
DeserializeObject<Dictionary<string, object>> benim için harika çalıştı; İhtiyaçlarım için bir dizi sözlüke dönüştürmeyi bitirdim. DeserializeObject<Dictionary<string, object>[]>. - BrainSlugs83


Ben hiçbiri gerçekten çivilenmiş gibi her iki yanıtın bir karışımı kullanarak sona erdi.

ToObject (), bir JSON nesnesindeki özelliklerin ilk düzeyini yapabilir, ancak iç içe geçmiş nesneler Dictionary () öğesine dönüştürülmez.

Ayrıca, ToObject () öğesinin birinci seviye özelliklerle oldukça iyi olması nedeniyle her şeyi manuel olarak yapmaya gerek yoktur.

İşte kod:

public static class JObjectExtensions
{
    public static IDictionary<string, object> ToDictionary(this JObject @object)
    {
        var result = @object.ToObject<Dictionary<string, object>>();

        var JObjectKeys = (from r in result
                           let key = r.Key
                           let value = r.Value
                           where value.GetType() == typeof(JObject)
                           select key).ToList();

        var JArrayKeys = (from r in result
                          let key = r.Key
                          let value = r.Value
                          where value.GetType() == typeof(JArray)
                          select key).ToList();

        JArrayKeys.ForEach(key => result[key] = ((JArray)result[key]).Values().Select(x => ((JValue)x).Value).ToArray());
        JObjectKeys.ForEach(key => result[key] = ToDictionary(result[key] as JObject));

        return result;
    }
}

Çalışmayacağı kenar durumları olabilir ve performans onun en güçlü kalitesi değildir.

Teşekkürler beyler!


19
2018-02-15 21:22



Dizinin değerleri JSON ise (ör. JObject) kendileri? Onları dönüştürmüyorsun Dictionary<string,object> - Nawaz
@Nawaz, sanırım yapar - son kod satırına giden ikinci yöntem, bu yöntemi içsel olarak yinelemeli olarak çağırır. JObjects. - BrainSlugs83
@ BrainSlugs83: Evet. Yinelemeli olarak çağırıyor ama yine de JArrays olabilirdi JOBject veya JArrraysonra o zamanlar C # dizisi, ve C # Sözlükkodun yapmadığı - Nawaz
@ BrainSlugs83 Bu yorumu yayınladıktan sonra bir süre olduğunu biliyorum, ama% 100 haklısın. JArray'ınızın JArray'dan oluştuğu senaryoda, anahtarı nasıl doldurursunuz? Sözlük <string, object> veri yapısı, bir özellik adı olmadan potansiyel olarak iki yuvalama seviyesi için düz düşer. - Miek


İşte başlangıç ​​sürümü: Kodu değiştirdim rekor JArrays bir JObjects iç içe JArrays / JObjectskabul edilen cevap, Nuh tarafından işaret edildiği gibi değil.

using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;

public static class JsonConversionExtensions
{
    public static IDictionary<string, object> ToDictionary(this JObject json)
    {
        var propertyValuePairs = json.ToObject<Dictionary<string, object>>();
        ProcessJObjectProperties(propertyValuePairs);
        ProcessJArrayProperties(propertyValuePairs);
        return propertyValuePairs;
    }

    private static void ProcessJObjectProperties(IDictionary<string, object> propertyValuePairs)
    {
        var objectPropertyNames = (from property in propertyValuePairs
            let propertyName = property.Key
            let value = property.Value
            where value is JObject
            select propertyName).ToList();

        objectPropertyNames.ForEach(propertyName => propertyValuePairs[propertyName] = ToDictionary((JObject) propertyValuePairs[propertyName]));
    }

    private static void ProcessJArrayProperties(IDictionary<string, object> propertyValuePairs)
    {
        var arrayPropertyNames = (from property in propertyValuePairs
            let propertyName = property.Key
            let value = property.Value
            where value is JArray
            select propertyName).ToList();

        arrayPropertyNames.ForEach(propertyName => propertyValuePairs[propertyName] = ToArray((JArray) propertyValuePairs[propertyName]));
    }

    public static object[] ToArray(this JArray array)
    {
        return array.ToObject<object[]>().Select(ProcessArrayEntry).ToArray();
    }

    private static object ProcessArrayEntry(object value)
    {
        if (value is JObject)
        {
            return ToDictionary((JObject) value);
        }
        if (value is JArray)
        {
            return ToArray((JArray) value);
        }
        return value;
    }
}

12
2017-09-22 20:03





Uzatma yöntemleri için iyi bir kullanım örneği gibi geliyor - Json.NET'e (Teşekkürler NuGet!) Dönüştürmek oldukça kolaydı.

Tabii ki, bu çabucak birlikte hacklendi - onu temizlemek istiyorum, vb.

public static class JTokenExt
{
    public static Dictionary<string, object> 
         Bagify(this JToken obj, string name = null)
    {
        name = name ?? "obj";
        if(obj is JObject)
        {
            var asBag =
                from prop in (obj as JObject).Properties()
                let propName = prop.Name
                let propValue = prop.Value is JValue 
                    ? new Dictionary<string,object>()
                        {
                            {prop.Name, prop.Value}
                        } 
                    :  prop.Value.Bagify(prop.Name)
                select new KeyValuePair<string, object>(propName, propValue);
            return asBag.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
        }
        if(obj is JArray)
        {
            var vals = (obj as JArray).Values();
            var alldicts = vals
                .SelectMany(val => val.Bagify(name))
                .Select(x => x.Value)
                .ToArray();
            return new Dictionary<string,object>()
            { 
                {name, (object)alldicts}
            };
        }
        if(obj is JValue)
        {
            return new Dictionary<string,object>()
            { 
                {name, (obj as JValue)}
            };
        }
        return new Dictionary<string,object>()
        { 
            {name, null}
        };
    }
}

3
2018-02-15 05:53





İşte daha basit bir versiyon:

    public static object ToCollections(object o)
    {
        var jo = o as JObject;
        if (jo != null) return jo.ToObject<IDictionary<string, object>>().ToDictionary(k => k.Key, v => ToCollections(v.Value));
        var ja = o as JArray;
        if (ja != null) return ja.ToObject<List<object>>().Select(ToCollections).ToList();
        return o;
    }

C # 7 kullanıyorsanız, desen eşlemesini şu şekilde görünecek şekilde kullanabiliriz:

    public static object ToCollections(object o)
    {
        if (o is JObject jo) return jo.ToObject<IDictionary<string, object>>().ToDictionary(k => k.Key, v => ToCollections(v.Value));
        if (o is JArray ja) return ja.ToObject<List<object>>().Select(ToCollections).ToList();
        return o;
    }

0
2017-07-19 06:18