Désérialiser JSON en objet c # dynamic?

y a-t-il un moyen de desérialiser le contenu JSON en un type dynamique C# 4? Il serait agréable de sauter la création d'un tas de classes afin d'utiliser le DataContractJsonSerializer.

804
demandé sur Drew Noakes 2010-06-29 20:04:01

24 réponses

si vous êtes heureux d'avoir une dépendance sur l'ensemble System.Web.Helpers , alors vous pouvez utiliser la Json classe:

dynamic data = Json.Decode(json);

il est inclus dans le cadre MVC en tant que téléchargement supplémentaire dans le cadre .NET 4. Assurez-vous de donner Vlad un upvote si cela est utile! Cependant, si vous ne pouvez pas supposer que l'environnement du client inclut cette DLL, lisez la suite.


une autre méthode de désérialisation est suggérée ici . J'ai légèrement modifié le code pour corriger un bug et convenir à mon style de codage. Tout ce que 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));

ainsi, donné une chaîne de 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)
582
répondu Drew Noakes 2017-05-23 12:34:38

c'est assez simple en utilisant 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;

de la Documentation: l'Interrogation de JSON avec dynamique

507
répondu Tom Peplow 2015-01-30 22:08:19

vous pouvez le faire en utilisant le système .Web.Helper.Json - sa méthode de décodage renvoie un objet dynamique que vous pouvez parcourir comme bon vous semble.

C'est inclus dans le Système.Web.Assemblage des Helpers (.NET 4.0).

var dynamicObject = Json.Decode(jsonString);
284
répondu Vlad Iliescu 2013-04-15 10:19:01

.Net 4.0 dispose d'une bibliothèque intégrée pour ce faire:

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

C'est la manière la plus simple.

76
répondu Peter Long 2011-06-14 08:06:43

Simple "de la chaîne de données json" pour objet, sans tiers de la dll

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 

Note : Vous pouvez également utiliser votre objet personnalisé.

Personel item = serializer.Deserialize<Personel>(getString);
70
répondu İbrahim Özbölük 2014-03-07 11:26:03

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

https://github.com/jsonfx/jsonfx

Sérialiser/à partir de dynamique des types (par défaut pour les .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
répondu jbtule 2018-02-07 06:12:13

j'ai fait une nouvelle version du DynamicJsonConverter qui utilise des 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) })); }
        }
    }
}  
17
répondu Jason Bolton 2011-06-07 07:31:13

une autre façon d'utiliser Newtonsoft.Json :

dynamic stuff = Newtonsoft.Json.JsonConvert.DeserializeObject("{ color: 'red', value: 5 }");
string color = stuff.color;
int value = stuff.value;
14
répondu Jonas Lundgren 2013-04-09 19:19:59

la manière la plus simple est

incluez juste ce dll

utilisez le code comme ceci

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
répondu user1006544 2012-12-26 11:15:42

vous pouvez étendre le JavaScriptSerializer pour recursively copier le dictionnaire qu'il a créé pour expando objet (s) et ensuite les utiliser dynamiquement:

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

alors vous avez juste besoin d'avoir une déclaration d'utilisation pour l'espace de noms que vous avez défini l'extension dans (considérez juste les définir dans le système.Web.Script.Sérialisation... une autre astuce est de ne pas utiliser un espace de noms, alors vous n'avez pas besoin de la déclaration d'utilisation du tout) et vous pouvez les consommer comme cela:

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
répondu alonzofox 2011-11-30 21:56:29

pour que j'utiliserais JSON.NET pour effectuer l'analyse de bas niveau du flux JSON et ensuite construire la hiérarchie des objets à partir des instances de la classe ExpandoObject .

5
répondu Daniel Earwicker 2010-06-29 16:07:38

j'utilise comme ça dans mon code et ça marche très bien

using System.Web.Script.Serialization;
JavaScriptSerializer oJS = new JavaScriptSerializer();
RootObject oRootObject = new RootObject();
oRootObject = oJS.Deserialize<RootObject>(Your JSon String);
5
répondu Vasim Shaikh 2015-08-10 20:08:27

j'utilise: http://json2csharp.com / pour obtenir Une classe représentant l'Objet Json.

entrée:

{
   "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 ça j'utilise Newtonsoft.Json pour remplir 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 votre nom de variable json n'est pas valide C # name (nom commençant par $ ) vous pouvez corriger cela comme ceci:

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
répondu RoJaIt 2017-06-10 16:40:36

vous pouvez utiliser using Newtonsoft.Json

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

resolvedEvent.Event.Data est ma réponse en appelant l'événement principal .

5
répondu Vivek Shukla 2017-07-06 19:33:58

C'est probablement un peu tard pour vous aider mais L'objet que vous voulez DynamicJSONObject est inclus dans le système.Web.Helper.dll de la ASP.NET paquet de Pages Web, qui fait partie de WebMatrix.

4
répondu Nick Daniels 2010-12-20 16:16:24

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

il supporte .net 3.5+, silverlight et Windows phone 7.

prend en charge la dynamique pour .net 4.0

peut aussi être installé en tant que paquet nuget

Install-Package SimpleJson
4
répondu prabir 2012-02-20 15:21:53

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

juste à côté client utiliser la fonction eval pour l'exemple

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

puis utiliser

d[0][0].a / / / Sortie 1 du tableau 0 ligne 0

d[1][1].b / / sortie 59 du tableau 1 Ligne 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
répondu Behnam Mohammadi 2014-01-28 07:47:53

Deserializing in JSON.NET peut être dynamique en utilisant la classe JObject , qui est 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 faire référence aux 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
répondu Chad Kuehn 2015-07-30 16:01:16

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 à re-poster ici, et encore moins de point puisque cet article a une pièce jointe avec le fichier source clé/requis.

4
répondu vitaly-t 2016-09-21 14:25:19

pour obtenir un ExpandoObject:

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

Container container = JsonConvert.Deserialize<Container>(jsonAsString, new ExpandoObjectConverter());
3
répondu Ryan Norbauer 2014-03-04 05:18:20

essayer ce - que

  var units = new { Name = "Phone", Color= "White" };
    var jsonResponse = JsonConvert.DeserializeAnonymousType(json, units );
3
répondu Nirupam 2015-03-07 08:47:00

une autre option est de" coller JSON comme classes " de sorte qu'il puisse être désérialisé rapidement et facilement.

  1. copiez simplement votre JSON entier
  2. Dans VS: Cliquez sur Edition > collage Spécial > Coller JSON que de classes

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

1
répondu nitsram 2018-03-17 03:55:23

comment analyser easy json avec dynamic & JavaScriptSerializer

ajouter la référence du système .Web.Extensions et ajouter cet espace de nom 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 json complexes et imbriqués avec dynamic & JavaScriptSerializer

ajouter la référence du système .Web.Extensions et ajouter cet espace de nom 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();
}
1
répondu Mist 2018-05-21 09:54:21

Avec Cinchoo ETL - une bibliothèque open source disponibles pour parser du 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

Avertissement: je suis l'auteur de cette bibliothèque.

0
répondu RajN 2018-09-07 01:42:08