web-dev-qa-db-fra.com

Désérialiser JSON en objet dynamique C #?

Existe-t-il un moyen de désérialiser le contenu JSON en un type dynamique C # 4? Il serait bien de ne pas créer un groupe de classes pour pouvoir utiliser DataContractJsonSerializer. 

839
jswanson

Si vous préférez avoir une dépendance sur l'assembly System.Web.Helpers, vous pouvez utiliser la classe Json :

dynamic data = Json.Decode(json);

Il est inclus avec le framework MVC en tant que téléchargement supplémentaire vers le framework .NET 4. Assurez-vous de donner à Vlad un vote positif si cela vous aide! Toutefois, si vous ne pouvez pas supposer que l'environnement client inclut cette DLL, lisez la suite.


Une approche alternative de désérialisation est suggérée ici . J'ai légèrement modifié le code pour corriger un bogue et convenir à mon style de codage. Tout ce dont vous avez besoin est ce code et une référence à System.Web.Extensions de votre projet:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Web.Script.Serialization;

public sealed class DynamicJsonConverter : JavaScriptConverter
{
    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        if (dictionary == null)
            throw new ArgumentNullException("dictionary");

        return type == typeof(object) ? new DynamicJsonObject(dictionary) : null;
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override IEnumerable<Type> SupportedTypes
    {
        get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(object) })); }
    }

    #region Nested type: DynamicJsonObject

    private sealed class DynamicJsonObject : DynamicObject
    {
        private readonly IDictionary<string, object> _dictionary;

        public DynamicJsonObject(IDictionary<string, object> dictionary)
        {
            if (dictionary == null)
                throw new ArgumentNullException("dictionary");
            _dictionary = dictionary;
        }

        public override string ToString()
        {
            var sb = new StringBuilder("{");
            ToString(sb);
            return sb.ToString();
        }

        private void ToString(StringBuilder sb)
        {
            var firstInDictionary = true;
            foreach (var pair in _dictionary)
            {
                if (!firstInDictionary)
                    sb.Append(",");
                firstInDictionary = false;
                var value = pair.Value;
                var name = pair.Key;
                if (value is string)
                {
                    sb.AppendFormat("{0}:\"{1}\"", name, value);
                }
                else if (value is IDictionary<string, object>)
                {
                    new DynamicJsonObject((IDictionary<string, object>)value).ToString(sb);
                }
                else if (value is ArrayList)
                {
                    sb.Append(name + ":[");
                    var firstInArray = true;
                    foreach (var arrayValue in (ArrayList)value)
                    {
                        if (!firstInArray)
                            sb.Append(",");
                        firstInArray = false;
                        if (arrayValue is IDictionary<string, object>)
                            new DynamicJsonObject((IDictionary<string, object>)arrayValue).ToString(sb);
                        else if (arrayValue is string)
                            sb.AppendFormat("\"{0}\"", arrayValue);
                        else
                            sb.AppendFormat("{0}", arrayValue);

                    }
                    sb.Append("]");
                }
                else
                {
                    sb.AppendFormat("{0}:{1}", name, value);
                }
            }
            sb.Append("}");
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (!_dictionary.TryGetValue(binder.Name, out result))
            {
                // return null to avoid exception.  caller can check for null this way...
                result = null;
                return true;
            }

            result = WrapResultObject(result);
            return true;
        }

        public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
        {
            if (indexes.Length == 1 && indexes[0] != null)
            {
                if (!_dictionary.TryGetValue(indexes[0].ToString(), out result))
                {
                    // return null to avoid exception.  caller can check for null this way...
                    result = null;
                    return true;
                }

                result = WrapResultObject(result);
                return true;
            }

            return base.TryGetIndex(binder, indexes, out result);
        }

        private static object WrapResultObject(object result)
        {
            var dictionary = result as IDictionary<string, object>;
            if (dictionary != null)
                return new DynamicJsonObject(dictionary);

            var arrayList = result as ArrayList;
            if (arrayList != null && arrayList.Count > 0)
            {
                return arrayList[0] is IDictionary<string, object> 
                    ? new List<object>(arrayList.Cast<IDictionary<string, object>>().Select(x => new DynamicJsonObject(x))) 
                    : new List<object>(arrayList.Cast<object>());
            }

            return result;
        }
    }

    #endregion
}

Vous pouvez l'utiliser comme ceci:

string json = ...;

var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new DynamicJsonConverter() });

dynamic obj = serializer.Deserialize(json, typeof(object));

Donc, étant donné une chaîne JSON:

{
  "Items":[
    { "Name":"Apple", "Price":12.3 },
    { "Name":"Grape", "Price":3.21 }
  ],
  "Date":"21/11/2010"
}

Le code suivant fonctionnera à l'exécution:

dynamic data = serializer.Deserialize(json, typeof(object));

data.Date; // "21/11/2010"
data.Items.Count; // 2
data.Items[0].Name; // "Apple"
data.Items[0].Price; // 12.3 (as a decimal)
data.Items[1].Name; // "Grape"
data.Items[1].Price; // 3.21 (as a decimal)
600
Drew Noakes

C'est assez simple avec Json.NET :

dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");

string name = stuff.Name;
string address = stuff.Address.City;

Aussi using Newtonsoft.Json.Linq:

dynamic stuff = JObject.Parse("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");

string name = stuff.Name;
string address = stuff.Address.City;

Documentation: Interrogation de JSON avec dynamique

540
Tom Peplow

Vous pouvez le faire en utilisant System.Web.Helpers.Json - sa méthode Decode renvoie un objet dynamique que vous pouvez parcourir à votre guise.

Il est inclus dans l'assembly System.Web.Helpers (.NET 4.0).

var dynamicObject = Json.Decode(jsonString);
287
Vlad Iliescu

NET 4.0 a une bibliothèque intégrée pour faire ceci:

using System.Web.Script.Serialization;
JavaScriptSerializer jss = new JavaScriptSerializer();
var d=jss.Deserialize<dynamic>(str);

C'est le moyen le plus simple.

78
Peter Long

"Chaîne json data" simple à objecter sans dll tierce

WebClient client = new WebClient();
string getString = client.DownloadString("https://graph.facebook.com/zuck");


JavaScriptSerializer serializer = new JavaScriptSerializer(); 
dynamic item = serializer.Deserialize<object>(getString);
string name = item["name"];

//note: JavaScriptSerializer in this namespaces
//System.Web.Script.Serialization.JavaScriptSerializer 

Remarque: vous pouvez également utiliser votre objet personnalisé. 

Personel item = serializer.Deserialize<Personel>(getString);
73

JsonFx peut désérialiser JSON en objets dynamiques.

https://github.com/jsonfx/jsonfx

Sérialiser vers/à partir de types dynamiques (valeur par défaut pour .NET 4.0):

var reader = new JsonReader(); var writer = new JsonWriter();

string input = @"{ ""foo"": true, ""array"": [ 42, false, ""Hello!"", null ] }";
dynamic output = reader.Read(input);
Console.WriteLine(output.array[0]); // 42
string json = writer.Write(output);
Console.WriteLine(json); // {"foo":true,"array":[42,false,"Hello!",null]}
28
jbtule

J'ai créé une nouvelle version de DynamicJsonConverter qui utilise les objets Expando. J'ai utilisé des objets expando parce que je voulais sérialiser la dynamique dans json en utilisant Json.net.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Dynamic;
using System.Web.Script.Serialization;

public static class DynamicJson
{
    public static dynamic Parse(string json)
    {
        JavaScriptSerializer jss = new JavaScriptSerializer();
        jss.RegisterConverters(new JavaScriptConverter[] { new DynamicJsonConverter() });

        dynamic glossaryEntry = jss.Deserialize(json, typeof(object)) as dynamic;
        return glossaryEntry;
    }

    class DynamicJsonConverter : JavaScriptConverter
    {
        public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
        {
            if (dictionary == null)
                throw new ArgumentNullException("dictionary");

            var result = ToExpando(dictionary);

            return type == typeof(object) ? result : null;
        }

        private static ExpandoObject ToExpando(IDictionary<string, object> dictionary)
        {
            var result = new ExpandoObject();
            var dic = result as IDictionary<String, object>;

            foreach (var item in dictionary)
            {
                var valueAsDic = item.Value as IDictionary<string, object>;
                if (valueAsDic != null)
                {
                    dic.Add(item.Key, ToExpando(valueAsDic));
                    continue;
                }
                var arrayList = item.Value as ArrayList;
                if (arrayList != null && arrayList.Count > 0)
                {
                    dic.Add(item.Key, ToExpando(arrayList));
                    continue;
                }

                dic.Add(item.Key, item.Value);
            }
            return result;
        }

        private static ArrayList ToExpando(ArrayList obj)
        {
            ArrayList result = new ArrayList();

            foreach (var item in obj)
            {
                var valueAsDic = item as IDictionary<string, object>;
                if (valueAsDic != null)
                {
                    result.Add(ToExpando(valueAsDic));
                    continue;
                }

                var arrayList = item as ArrayList;
                if (arrayList != null && arrayList.Count > 0)
                {
                    result.Add(ToExpando(arrayList));
                    continue;
                }

                result.Add(item);
            }
            return result;
        }

        public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
        {
            throw new NotImplementedException();
        }

        public override IEnumerable<Type> SupportedTypes
        {
            get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(object) })); }
        }
    }
}  
18
Jason Bolton

Une autre façon en utilisant Newtonsoft.Json :

dynamic stuff = Newtonsoft.Json.JsonConvert.DeserializeObject("{ color: 'red', value: 5 }");
string color = stuff.color;
int value = stuff.value;
14
Jonas Lundgren

Le plus simple est 

Il suffit d’inclure ceci dll

utiliser le code comme ça

dynamic json = new JDynamic("{a:'abc'}");
//json.a is a string "abc"

dynamic json = new JDynamic("{a:3.1416}");
//json.a is 3.1416m

dynamic json = new JDynamic("{a:1}");
//json.a is

dynamic json = new JDynamic("[1,2,3]");
/json.Length/json.Count is 3
//And you can use json[0]/ json[2] to get the elements

dynamic json = new JDynamic("{a:[1,2,3]}");
//json.a.Length /json.a.Count is 3.
//And you can use  json.a[0]/ json.a[2] to get the elements

dynamic json = new JDynamic("[{b:1},{c:1}]");
//json.Length/json.Count is 2.
//And you can use the  json[0].b/json[1].c to get the num.
7
user1006544

Vous pouvez étendre JavaScriptSerializer pour copier de manière récursive le dictionnaire créé pour développer des objets, puis les utiliser de manière dynamique:

static class JavaScriptSerializerExtensions
{
    public static dynamic DeserializeDynamic(this JavaScriptSerializer serializer, string value)
    {
        var dictionary = serializer.Deserialize<IDictionary<string, object>>(value);
        return GetExpando(dictionary);
    }

    private static ExpandoObject GetExpando(IDictionary<string, object> dictionary)
    {
        var expando = (IDictionary<string, object>)new ExpandoObject();

        foreach (var item in dictionary)
        {
            var innerDictionary = item.Value as IDictionary<string, object>;
            if (innerDictionary != null)
            {
                expando.Add(item.Key, GetExpando(innerDictionary));
            }
            else
            {
                expando.Add(item.Key, item.Value);
            }
        }

        return (ExpandoObject)expando;
    }
}

Ensuite, vous devez simplement avoir une instruction using pour l’espace de nommage dans lequel vous avez défini l’extension (pensez simplement à les définir dans System.Web.Script.Serialization ... un autre truc consiste à ne pas utiliser d’espace déclaration du tout) et vous pouvez les consommer comme suit:

var serializer = new JavaScriptSerializer();
var value = serializer.DeserializeDynamic("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");

var name = (string)value.Name; // Jon Smith
var age = (int)value.Age;      // 42

var address = value.Address;
var city = (string)address.City;   // New York
var state = (string)address.State; // NY
6
alonzofox

Vous pouvez utiliser using Newtonsoft.Json

var jRoot = 
 JsonConvert.DeserializeObject<dynamic>(Encoding.UTF8.GetString(resolvedEvent.Event.Data));

resolvedEvent.Event.Data est ma réponse après l'appel de l'événement central.

6
Vivek Shukla

J'utilise: http://json2csharp.com/ Pour obtenir une classe représentant l'objet Json.

Contribution:

{
   "name":"John",
   "age":31,
   "city":"New York",
   "Childs":[
      {
         "name":"Jim",
         "age":11
      },
      {
         "name":"Tim",
         "age":9
      }
   ]
}

Sortie:

public class Child
{
    public string name { get; set; }
    public int age { get; set; }
}

public class Person
{
    public string name { get; set; }
    public int age { get; set; }
    public string city { get; set; }
    public List<Child> Childs { get; set; }
}

Après cela, j'utilise Newtonsoft.Json pour renseigner la classe:

using Newtonsoft.Json;

namespace GitRepositoryCreator.Common
{
    class JObjects
    {
        public static string Get(object p_object)
        {
            return JsonConvert.SerializeObject(p_object);
        }
        internal static T Get<T>(string p_object)
        {
            return JsonConvert.DeserializeObject<T>(p_object);
        }
    }
}

Vous pouvez l'appeler comme ça:

Person jsonClass = JObjects.Get<Person>(stringJson);

string stringJson = JObjects.Get(jsonClass);

PS: 

Si le nom de votre variable json n'est pas un nom C # valide (le nom commence par $), vous pouvez résoudre ce problème comme suit:

public class Exception
{
   [JsonProperty(PropertyName = "$id")]
   public string id { get; set; }
   public object innerException { get; set; }
   public string message { get; set; }
   public string typeName { get; set; }
   public string typeKey { get; set; }
   public int errorCode { get; set; }
   public int eventId { get; set; }
}
5
RoJaIt

Pour cela, j'utiliserais JSON.NET pour effectuer l'analyse de bas niveau du flux JSON, puis créer la hiérarchie d'objets à partir d'instances de la classe ExpandoObject.

5
Daniel Earwicker

Regardez l'article que j'ai écrit sur CodeProject, qui répond précisément à la question:

Types dynamiques avec JSON.NET

Il y a beaucoup trop de choses pour tout republier ici, et encore moins parce que cet article a une pièce jointe avec le fichier source clé/requis.

5
vitaly-t

J'utilise comme ça dans mon code et ça fonctionne bien

using System.Web.Script.Serialization;
JavaScriptSerializer oJS = new JavaScriptSerializer();
RootObject oRootObject = new RootObject();
oRootObject = oJS.Deserialize<RootObject>(Your JSon String);
5
Vasim Shaikh

Il existe une bibliothèque JSON légère pour C # appelée SimpleJson qui peut être trouvée à l'adresse http://simplejson.codeplex.com https://github.com/facebook-csharp-sdk/simple-json

Il prend en charge .net 3.5+, silverlight et windows phone 7.

Prise en charge dynamique pour .net 4.0

Peut aussi être installé comme un paquet de nuget

Install-Package SimpleJson
4
prabir

La désérialisation dans JSON.NET peut être dynamique à l'aide de la classe JObject, incluse dans cette bibliothèque. Ma chaîne JSON représente ces classes:

public class Foo {
   public int Age {get;set;}
   public Bar Bar {get;set;}
}

public class Bar {
   public DateTime BDay {get;set;}
}

Maintenant, nous désérialisons la chaîne SANS référencer les classes ci-dessus:

var dyn = JsonConvert.DeserializeObject<JObject>(jsonAsFooString);

JProperty propAge = dyn.Properties().FirstOrDefault(i=>i.Name == "Age");
if(propAge != null) {
    int age = int.Parse(propAge.Value.ToString());
    Console.WriteLine("age=" + age);
}

//or as a one-liner:
int myage = int.Parse(dyn.Properties().First(i=>i.Name == "Age").Value.ToString());

Ou si vous voulez aller plus loin:

var propBar = dyn.Properties().FirstOrDefault(i=>i.Name == "Bar");
if(propBar != null) {
    JObject o = (JObject)propBar.First();
    var propBDay = o.Properties().FirstOrDefault (i => i.Name=="BDay");
    if(propBDay != null) {
        DateTime bday = DateTime.Parse(propBDay.Value.ToString());
        Console.WriteLine("birthday=" + bday.ToString("MM/dd/yyyy"));
    }
}

//or as a one-liner:
DateTime mybday = DateTime.Parse(((JObject)dyn.Properties().First(i=>i.Name == "Bar").First()).Properties().First(i=>i.Name == "BDay").Value.ToString());

Voir post pour un exemple complet.

4
Chad Kuehn

utiliser DataSet (C #) avec javascript fonction simple pour créer un flux json avec entrée DataSet créer json comme (ensemble de données multi-tables) [[{a: 1, b: 2, c: 3}, { a: 3, b: 5, c: 6}], [{a: 23, b: 45, c: 35}, {a: 58, b: 59, c: 45}]]

juste utilisation côté client eval par exemple

var d = eval ('[[{a: 1, b: 2, c: 3}, {a: 3, b: 5, c: 6}], [{a: 23, b: 45, c: 35 }, {a: 58, b: 59, c: 45}]] ')

puis utiliser 

d [0] [0] .a // sortie 1 du tableau 0 rangée 0

d [1] [1] .b // sortie 59 du tableau 1 rangée 1

//create by Behnam Mohammadi And Saeed Ahmadian
public string jsonMini(DataSet ds)
{
    int t=0, r=0, c=0;
    string stream = "[";

    for (t = 0; t < ds.Tables.Count; t++)
    {
        stream += "[";
        for (r = 0; r < ds.Tables[t].Rows.Count; r++)
        {
            stream += "{";
            for (c = 0; c < ds.Tables[t].Columns.Count; c++)
            {
                stream += ds.Tables[t].Columns[c].ToString() + ":'" + ds.Tables[t].Rows[r][c].ToString() + "',";
            }
            if(c>0)
                stream = stream.Substring(0, stream.Length - 1);
            stream += "},";
        }
        if(r>0)
            stream = stream.Substring(0, stream.Length - 1);
        stream += "],";
    }
    if(t>0)
        stream = stream.Substring(0, stream.Length - 1);
    stream += "];";
    return stream;
}
4
Behnam Mohammadi

essaye ça - 

  var units = new { Name = "Phone", Color= "White" };
    var jsonResponse = JsonConvert.DeserializeAnonymousType(json, units );
4
Nirupam

C'est probablement un peu tard pour vous aider, mais l'objet que vous voulez DynamicJSONObject est inclus dans System.Web.Helpers.dll du package ASP.NET Web Pages, qui fait partie de WebMatrix.

4
Nick Daniels

Pour obtenir un ExpandoObject:

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

Container container = JsonConvert.Deserialize<Container>(jsonAsString, new ExpandoObjectConverter());
3
Ryan Norbauer

Comment analyser easy json avec dynamic & JavaScriptSerializer

Veuillez ajouter la référence de System.Web.Extensions et ajouter cet espace de noms using System.Web.Script.Serialization; en haut.

public static void EasyJson()
{
    var jsonText = @"{
        ""some_number"": 108.541, 
        ""date_time"": ""2011-04-13T15:34:09Z"", 
        ""serial_number"": ""SN1234""
    }";

    var jss = new JavaScriptSerializer();
    var dict = jss.Deserialize<dynamic>(jsonText);

    Console.WriteLine(dict["some_number"]); 
    Console.ReadLine();
}

Comment analyser les fichiers json imbriqués et complexes avec dynamic & JavaScriptSerializer

Veuillez ajouter la référence de System.Web.Extensions et ajouter cet espace de noms using System.Web.Script.Serialization; en haut.

public static void ComplexJson()
{
    var jsonText = @"{
        ""some_number"": 108.541, 
        ""date_time"": ""2011-04-13T15:34:09Z"", 
        ""serial_number"": ""SN1234"",
        ""more_data"": {
            ""field1"": 1.0,
            ""field2"": ""hello""
        }
    }";

    var jss = new JavaScriptSerializer();
    var dict = jss.Deserialize<dynamic>(jsonText);

    Console.WriteLine(dict["some_number"]); 
    Console.WriteLine(dict["more_data"]["field2"]);
    Console.ReadLine();
}
2
Mist

Vous pouvez y parvenir avec l'aide de Newtonsoft.Json. Installez Newtonsoft.Json à partir de Nuget et le:

using Newtonsoft.Json;

dynamic results = JsonConvert.DeserializeObject<dynamic>(YOUR_JSON);
1
Waleed Naveed

Une autre option consiste à "Coller JSON en tant que classes" afin de pouvoir le désérialiser rapidement et facilement.

  1. Copiez simplement votre JSON entier
  2. Dans VS: Cliquez sur Edition> Collage spécial> Coller JSON en tant que classes.

Voici une meilleure explication des piccas ... https://blogs.msdn.Microsoft.com/webdev/2012/12/18/paste-json-as-classes-in-asp-net-and-web- outils-2012-2-rc/

1
nitsram

essayez de cette façon!

Exemple JSON:

  [{
            "id": 140,
            "group": 1,
            "text": "xxx",
            "creation_date": 123456,
            "created_by": "[email protected]",
            "tags": ["xxxxx"]
        }, {
            "id": 141,
            "group": 1,
            "text": "xxxx",
            "creation_date": 123456,
            "created_by": "[email protected]",
            "tags": ["xxxxx"]
        }]

Code C #:

        var jsonString = (File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(),"delete_result.json")));
        var objects = JsonConvert.DeserializeObject<dynamic>(jsonString);
        foreach(var o in objects)
        {
            Console.WriteLine($"{o.id.ToString()}");
        }
0
Blue Steel

With Cinchoo ETL - une bibliothèque open source disponible pour analyser json en objet dynamique

string json = @"{
    ""key1"": [
        {
            ""action"": ""open"",
            ""timestamp"": ""2018-09-05 20:46:00"",
            ""url"": null,
            ""ip"": ""66.102.6.98""
        }
    ]
}";
using (var p = ChoJSONReader.LoadText(json)
    .WithJSONPath("$.*")
    )
{
    foreach (var rec in p)
    {
        Console.WriteLine("action: " + rec.action);
        Console.WriteLine("timestamp: " + rec.timestamp);
        Console.WriteLine("url: " + rec.url);
        Console.WriteLine("ip: " + rec.ip);
    }
}

Sortie:

action: open
timestamp: 2018-09-05 20:46:00
url: http://www.google.com
ip: 66.102.6.98

Disclaimer: Je suis l'auteur de cette bibliothèque.

0
RajN