Wie kann ich JSON mit C # analysieren?

455

Ich habe folgenden Code:

var user = (Dictionary<string, object>)serializer.DeserializeObject(responsecontent);

Die Eingabe in responsecontentist JSON, wird jedoch nicht ordnungsgemäß in ein Objekt analysiert. Wie soll ich es richtig deserialisieren?

Ola Ström
quelle
7
Hey, vielleicht möchten Sie diesen Link versuchen techblog.procurios.nl/k/n618/news/view/14605/14863/…
Vamsi
34
Es gibt Jsonin System.Web.Helpers, es gibt JsonQueryStringConverterin System.ServiceModel.Web, es gibt JavascriptSerializerin System.Web.Script.Serialization, DataContractJsonSerializerin System.Runtime.Serialization.Json, zum Teufel MS hat sogar beschlossen, Dritte Json.NETin seine ASP.NET-Web-API aufzunehmen. Wenn Sie dachten, dass das nicht genug ist, kommt MS auf den Markt, ist System.Jsonaber derzeit nicht für den Konsum geeignet. Weiter so Microsoft Weiter so .... Ich wähle nach dem am besten aussehenden Namespace.
Nawfal
4
@fusi der Rest sind in separaten Baugruppen. Google den Namespace / Klassennamen, finden Sie die Assembly, die sie in der MSDN-Dokumentation sind. Fügen Sie einfach einen Verweis auf diese Baugruppe hinzu.
Nawfal
1
Gerade abgeschlossen ist , gibt es auch JsonValuein Windows.Data.Jsondem nur für Windows 8 und höher. Ich liebe es. MS ist auf einer Mission :)
Nawfal
5
NewtonSoft hat eine Vergleichsseite auf seiner Website (möglicherweise voreingenommen, aber immer noch interessant): newtonsoft.com/json/help/html/jsonnetvsdotnetserializers.htm . Mir hat besonders die Reihe der unsinnigen Wörterbuchserialisierung gefallen :)
Ohad Schneider

Antworten:

365

Ich gehe davon aus, dass Sie Json.NET (Newtonsoft.Json NuGet-Paket) nicht verwenden. Wenn dies der Fall ist, sollten Sie es versuchen.

Es hat die folgenden Funktionen:

  1. LINQ zu JSON
  2. Der JsonSerializer zum schnellen Konvertieren Ihrer .NET-Objekte in JSON und wieder zurück
  3. Json.NET kann optional gut formatiertes, eingerücktes JSON zum Debuggen oder Anzeigen erstellen
  4. Attribute wie JsonIgnore und JsonProperty können einer Klasse hinzugefügt werden, um die Serialisierung einer Klasse anzupassen
  5. Möglichkeit, JSON in und aus XML zu konvertieren
  6. Unterstützt mehrere Plattformen: .NET, Silverlight und das Compact Framework

Schauen Sie sich das folgende Beispiel an . In diesem Beispiel wird die JsonConvertKlasse verwendet, um ein Objekt in und aus JSON zu konvertieren. Zu diesem Zweck gibt es zwei statische Methoden. Sie sind SerializeObject(Object obj)und DeserializeObject<T>(String json):

Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };

string json = JsonConvert.SerializeObject(product);
//{
//  "Name": "Apple",
//  "Expiry": "2008-12-28T00:00:00",
//  "Price": 3.99,
//  "Sizes": [
//    "Small",
//    "Medium",
//    "Large"
//  ]
//}

Product deserializedProduct = JsonConvert.DeserializeObject<Product>(json);
MD Sayem Ahmed
quelle
18
Kann ich in eine varTypvariable deserialisieren, falls ich die vollständige Struktur meines Ziels nicht kenne? Insbesondere konsumiere ich Rally User Stories und möchte sie in Objekte konvertieren.
Pedro Dusso
16
@VANDERWEYENJonathan - In einem modernen Webbrowser behandeln JSON.parse (Zeichenfolge) und JSON.stringify (Objekt) Datumsangaben als ISO8601-Zeichenfolgen. Dies ist das in der obigen Antwort dargestellte Format. Möglicherweise möchten Sie Ihren Standard aktualisieren, bevor die Benutzer entscheiden, dass er irrelevant ist. Die Leute brauchen viel mehr Daten als Ihren Standard.
Peter Wone
3
@PeterWone: Nein, JSON.parse('{"Expiry": "2008-12-28T00:00:00"}').Expirygibt die Zeichenfolge zurück "2008-12-28T00:00:00" , kein Datum. Es kann in ein DateVia umgewandelt werden new Date(str), JSON.parseweiß aber nichts über Daten. Sie müssten einen Reviver übergeben, der jeden einzelnen Zeichenfolgenwert mit einem Muster vergleicht.
TJ Crowder
3
Da 3,703 Sekunden gleich 3s und 703 ms sind und das Trennzeichen ein Dezimalpunkt ist, habe ich Ihnen gesagt, dass dies Sekunden bis drei Dezimalstellen sind.
Peter Wone
38
Warum hat jeder ein solches Problem mit einschließlich relevant require, include, importoder usingAussagen in ihren Antworten. Würde diese eine Zeile weh tun?
Tomáš Zato - Wiedereinsetzung Monica
285

Wie hier beantwortet - JSON in dynamisches C # -Objekt deserialisieren?

Mit Json.NET ist das ganz einfach:

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

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

Oder mit 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;
Dmitry Pavlov
quelle
13
@ MaxHodges, du hast recht. Ich habe gerade Inline- "Magic Strings" verwendet, um zu demonstrieren, wie JSON-String-Werte analysiert werden. Ich wollte nicht, dass es komplex aussieht, wenn doppelte Anführungszeichen angezeigt werden. Im realen Code haben wir normalerweise JSON-Zeichenfolgen, die von irgendwoher als Variablen abgerufen oder als Parameter übergeben werden.
Dmitry Pavlov
4
Ohne .net 4 haben Sie kein "dynamisches" Schlüsselwort. Sie können 'var stuff' für die Deklaration verwenden und anstelle von 'stuff.Name' und 'stuff.Address.City' haben Sie 'stuff ["Name"]' und 'stuff ["Address"] ["City"]' .
Fil
1
@Fil Das gibt Ihnen einen Wert vom Typ object, und Sie können die Indizierung für a nicht verwenden object.
Alex
138

Hier sind einige Optionen ohne Verwendung von Bibliotheken von Drittanbietern:

// For that you will need to add reference to System.Runtime.Serialization
var jsonReader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(@"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }"), new System.Xml.XmlDictionaryReaderQuotas());

// For that you will need to add reference to System.Xml and System.Xml.Linq
var root = XElement.Load(jsonReader);
Console.WriteLine(root.XPathSelectElement("//Name").Value);
Console.WriteLine(root.XPathSelectElement("//Address/State").Value);

// For that you will need to add reference to System.Web.Helpers
dynamic json = System.Web.Helpers.Json.Decode(@"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }");
Console.WriteLine(json.Name);
Console.WriteLine(json.Address.State);

Weitere Informationen zu System.Web.Helpers.Json finden Sie unter dem Link .

Update : Heutzutage ist es am einfachsten, Web.Helpersdas NuGet-Paket zu verwenden .


Wenn Sie sich nicht für frühere Windows-Versionen interessieren, können Sie die Klassen des Windows.Data.JsonNamespace verwenden:

// minimum supported version: Win 8
JsonObject root = Windows.Data.Json.JsonValue.Parse(jsonString).GetObject();
Console.WriteLine(root["Name"].GetString());
Console.WriteLine(root["Address"].GetObject()["State"].GetString());
qqbenq
quelle
Warum wird System.Web.Helpers auf meiner ASP.NET-Website (4.5) nicht angezeigt? XElement, XPathSelectElement sind für mein VisualStudio nicht bekannt. Wie erziehe ich es?
Budda
Nun, Sie müssen Referenzen für die entsprechenden Bibliotheken hinzufügen (wie in den obigen Kommentaren beschrieben). Weitere Informationen finden Sie in diesem Artikel . Auch diese Frage könnte von Interesse sein.
Qqbenq
2
Ich habe die hier beschriebene Web.Helpers-Methode verwendet, bin jedoch auf ein Problem gestoßen
Alex
1
es funktioniert mit WPF.By unter Verwendung des folgenden Namespace unter Verwendung von System.Runtime.Serialization.Json; using System.Xml.XPath; using System.Xml.Linq;
Shahid Neermunda
3
Json.Net ist kaum noch eine Komponente von Drittanbietern. Microsoft verwendet es heutzutage selbst. Dies ist der Standard-Serilizer für die Web-API.
Liam
62

Wenn Ihnen .NET 4 zur Verfügung steht, lesen Sie Folgendes: http://visitmix.com/writings/the-rise-of-json (archive.org)

Hier ist ein Ausschnitt von dieser Seite:

WebClient webClient = new WebClient();
dynamic result = JsonValue.Parse(webClient.DownloadString("https://api.foursquare.com/v2/users/self?oauth_token=XXXXXXX"));
Console.WriteLine(result.response.user.firstName);

Diese letzte Console.WriteLine ist ziemlich süß ...

ElonU Webdev
quelle
Es sieht so aus, als hätten sich die Dinge geändert, seit ich zum ersten Mal geantwortet habe. Ich muss mich umschauen und sehen, welche Bibliothek die richtige ist ...
ElonU Webdev
7
Ich freue mich darauf, diese Bibliothek zu finden. Bearbeiten: Ist es das: dynamicjson.codeplex.com ?
user989056
1
Ich weiß nicht, welche Klasse ElonU hier bedeutete, aber es gibt "JsonValue" in Windows.Data.Json (was nur für Windows 8 und höher ist - seltsam) und auch das gleiche "JsonValue" in System.Json, das sich noch in der Vorschau und befindet Gott allein weiß, ob es jemals herauskommen wird. MS verwirrt mich, wenn es um Json geht.
Nawfal
35

Eine weitere native Lösung hierfür, für die keine Bibliotheken von Drittanbietern erforderlich sind, sondern auf System.Web.Extensions verwiesen wird, ist der JavaScriptSerializer. Dies ist keine neue, aber eine sehr unbekannte integrierte Funktion seit 3.5.

using System.Web.Script.Serialization;

..

JavaScriptSerializer serializer = new JavaScriptSerializer();
objectString = serializer.Serialize(new MyObject());

und zurück

MyObject o = serializer.Deserialize<MyObject>(objectString)
fr34kyn01535
quelle
2
Dies ist sehr schön, benötigt jedoch die Webkomponenten, sodass es in .NET 4.0 Client Profile, der letzten .NET-Version für Windows XP, leider nicht funktioniert. Eine vollständige Installation von .NET ist möglich, aber viele Leute bleiben nur beim Client-Profil. Im Gegensatz dazu wird System.Runtime.Serialization.Json.DataContractJsonSerializer auch im Client-Profil unterstützt.
Al Kepp
3
@ fr34kyn01535: Windows XP hat den zweithäufigsten Marktanteil auf dem Desktop. Es ist relevant.
DonkeyMaster
Wenn ich JavaScriptSerializer zum Deseriarisieren meines Objekts verwendet habe, hat es funktioniert, aber mein Datum wurde deserialisiert. Es sollte am 19.04.2008 um 00:00 Uhr gewesen sein, aber am 18.04.2008 um 20:00 Uhr deserialisiert worden sein. NewtonSoft.Json.JsonConvert deserialisierte es wie erwartet.
Rich
21

Sie können sich auch den DataContractJsonSerializer ansehen

Pieter Germishuys
quelle
1
Dies ist besser, da es mit .NET 3.5
Mahmoud Fayez
es ist auch ziemlich schneller als JavaScriptSerializer,
David
16

System.Json funktioniert jetzt ...

Installieren Sie nuget https://www.nuget.org/packages/System.Json

PM> Install-Package System.Json -Version 4.5.0

Beispiel :

// PM>Install-Package System.Json -Version 4.5.0

using System;
using System.Json;

namespace NetCoreTestConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // Note that JSON keys are case sensitive, a is not same as A.

            // JSON Sample
            string jsonString = "{\"a\": 1,\"b\": \"string value\",\"c\":[{\"Value\": 1}, {\"Value\": 2,\"SubObject\":[{\"SubValue\":3}]}]}";

            // You can use the following line in a beautifier/JSON formatted for better view
            // {"a": 1,"b": "string value","c":[{"Value": 1}, {"Value": 2,"SubObject":[{"SubValue":3}]}]}

            /* Formatted jsonString for viewing purposes:
            {
               "a":1,
               "b":"string value",
               "c":[
                  {
                     "Value":1
                  },
                  {
                     "Value":2,
                     "SubObject":[
                        {
                           "SubValue":3
                        }
                     ]
                  }
               ]
            }
            */

            // Verify your JSON if you get any errors here
            JsonValue json = JsonValue.Parse(jsonString);

            // int test
            if (json.ContainsKey("a"))
            {
                int a = json["a"]; // type already set to int
                Console.WriteLine("json[\"a\"]" + " = " + a);
            }

            // string test
            if (json.ContainsKey("b"))
            {
                string b = json["b"];  // type already set to string
                Console.WriteLine("json[\"b\"]" + " = " + b);
            }

            // object array test
            if (json.ContainsKey("c") && json["c"].JsonType == JsonType.Array)
            {
                // foreach loop test
                foreach (JsonValue j in json["c"])
                {
                    Console.WriteLine("j[\"Value\"]" + " = " + j["Value"].ToString());
                }

                // multi level key test
                Console.WriteLine("json[\"c\"][0][\"Value\"]" + " = " + json["c"][0]["Value"].ToString());
                Console.WriteLine("json[\"c\"][0][\"Value\"]" + " = " + json["c"][1]["Value"].ToString());
                Console.WriteLine("json[\"c\"][1][\"SubObject\"][0][\"SubValue\"]" + " = " + json["c"][1]["SubObject"][0]["SubValue"].ToString());
            }

            Console.WriteLine();
            Console.Write("Press any key to exit.");
            Console.ReadKey();
        }
    }
}
Zunair
quelle
1
Der Versuch, ein Beispiel für die korrekte Verwendung des modernen System.Json zu finden, hat mich hierher gebracht, nachdem unzählige Ergebnisse für Json.NET/Newtonsoft.Json/"Newtson.Json "und ältere Iterationen von System.Json längst veraltet waren. Danke dafür.
monkey0506
1
Das hat mir sehr geholfen. Vielen Dank.
MAK
10

Verwenden Sie dieses Tool, um eine Klasse zu generieren, die auf Ihrem JSON basiert:

http://json2csharp.com/

Und dann verwenden Sie die Klasse, um Ihren JSON zu deserialisieren. Beispiel:

public class Account
{
    public string Email { get; set; }
    public bool Active { get; set; }
    public DateTime CreatedDate { get; set; }
    public IList<string> Roles { get; set; }
}


string json = @"{
  'Email': '[email protected]',
  'Active': true,
  'CreatedDate': '2013-01-20T00:00:00Z',
  'Roles': [
    'User',
    'Admin'
  ]
}";

Account account = JsonConvert.DeserializeObject<Account>(json);

Console.WriteLine(account.Email);
// [email protected]

Referenzen: https://forums.asp.net/t/1992996.aspx?Nested+Json+Deserialization+to+C+object+and+using+that+object https://www.newtonsoft.com/json/help /html/DeserializeObject.htm

Bruno Pereira
quelle
9

Versuchen Sie den folgenden Code:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("URL");
JArray array = new JArray();
using (var twitpicResponse = (HttpWebResponse)request.GetResponse())
using (var reader = new StreamReader(twitpicResponse.GetResponseStream()))
{
    JavaScriptSerializer js = new JavaScriptSerializer();
    var objText = reader.ReadToEnd();

    JObject joResponse = JObject.Parse(objText);
    JObject result = (JObject)joResponse["result"];
    array = (JArray)result["Detail"];
    string statu = array[0]["dlrStat"].ToString();
}
Muhammad Awais
quelle
Vielen Dank, ich wollte den Teil ["Ergebnis" + Variable], weil ich Variablen verwenden wollte, die hier verwendet werden sollen, was mit JSON.NET nicht einfach ist.
PHPGuru
Tut diese Zeile etwas ... JavaScriptSerializer js = new JavaScriptSerializer (); Danke im Voraus.
Chris Catignani
9

System.Text.Json

.NET Core 3.0 System.Text.Jsonist integriert. Dies bedeutet, dass Sie JSON ohne Verwendung einer Bibliothek eines Drittanbieters deserialisieren / serialisieren können .

So serialisieren Sie Ihre Klasse (n) in eine JSON-Zeichenfolge:

var json = JsonSerializer.Serialize(order);

So deserialisieren Sie den JSON in eine stark typisierte Klasse:

var order = JsonSerializer.Deserialize<Order>(json);

Wenn Sie also eine Klasse wie die folgende haben:

public class Order
{
    public int Id { get; set; }
    public string OrderNumber { get; set; }
    public decimal Balance { get; set; }
    public DateTime Opened { get; set; }
}

var json = JsonSerializer.Serialize(order);
// creates JSON ==>
{
    "id": 123456,
    "orderNumber": "ABC-123-456",
    "balance": 9876.54,
    "opened": "2019-10-21T23:47:16.85",
};

var order = JsonSerializer.Deserialize<Order>(json);
// ==> creates the above class

Beachten Sie, dass JSON-Eigenschaften bei Verwendung Ihres eigenen Codes System.Text.Json nicht automatisch verarbeitet werden (bei Verwendung von MVC / WebAPI-Anforderungen und des Modellbinders).camelCase

Um dies zu beheben, müssen Sie JsonSerializerOptionsals Parameter übergeben.

JsonSerializerOptions options = new JsonSerializerOptions
{        
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,  // set camelCase       
    WriteIndented = true                                // write pretty json
};

// pass options to serializer
var json = JsonSerializer.Serialize(order, options);
// pass options to deserializer
var order = JsonSerializer.Deserialize<Order>(json, options);

System.Text.Json ist auch für .Net Framework und .Net Standard als Nu-get-Paket System.Text.Json verfügbar

haldo
quelle
1
Was ist, wenn Sie keine Klasse haben? Was ist, wenn Sie nur vage wissen, was die JSON-Daten enthalten werden? Oder ob die Schlüssel überhaupt existieren?
Cherona
@Cherona verwenden JsonDocument.Parse.
Haldo
5

Das Folgende von der msdn- Site sollte meiner Meinung nach dazu beitragen, einige native Funktionen für das bereitzustellen, wonach Sie suchen. Bitte beachten Sie, dass es für Windows 8 spezifiziert ist. Ein solches Beispiel von der Site ist unten aufgeführt.

JsonValue jsonValue = JsonValue.Parse("{\"Width\": 800, \"Height\": 600, \"Title\": \"View from 15th Floor\", \"IDs\": [116, 943, 234, 38793]}");
double width = jsonValue.GetObject().GetNamedNumber("Width");
double height = jsonValue.GetObject().GetNamedNumber("Height");
string title = jsonValue.GetObject().GetNamedString("Title");
JsonArray ids = jsonValue.GetObject().GetNamedArray("IDs");

Es verwendet den Windows.Data.JSON- Namespace.

Ziel der Schwerkraft
quelle
6
Schön, aber "Minimum unterstützter Client: Windows 8"
watbywbarif
Ich denke, es wird nicht mehr unterstützt und jetzt gibt es newtonsoft json dll icouldnt windows.data.json finden
virtouso
3
@virtouso, wie watbywbarif betonte, ist eigentlich ziemlich neu, jedoch nur minimale Unterstützung von Microsoft , funktioniert nur unter Windows 8.
TargetofGravity
4

Sie können folgende Erweiterungen verwenden

public static class JsonExtensions
{
    public static T ToObject<T>(this string jsonText)
    {
        return JsonConvert.DeserializeObject<T>(jsonText);
    }

    public static string ToJson<T>(this T obj)
    {
        return JsonConvert.SerializeObject(obj);
    } 
}
Hidayet R. Colkusu
quelle
0

Ich denke, die beste Antwort, die ich gesehen habe, war @MD_Sayem_Ahmed.

Ihre Frage lautet "Wie kann ich Json mit C # analysieren?", Aber anscheinend möchten Sie Json entschlüsseln. Wenn Sie es entschlüsseln möchten, ist Ahmeds Antwort gut.

Wenn Sie dies in ASP.NET Web Api versuchen, können Sie am einfachsten ein Datenübertragungsobjekt erstellen, das die Daten enthält, die Sie zuweisen möchten:

public class MyDto{
    public string Name{get; set;}
    public string Value{get; set;}
}

Sie müssen Ihrer Anfrage einfach den Header application / json hinzufügen (wenn Sie beispielsweise Fiddler verwenden). Sie würden dies dann in der ASP.NET-Web-API wie folgt verwenden:

//controller method -- assuming you want to post and return data
public MyDto Post([FromBody] MyDto myDto){
   MyDto someDto = myDto;
   /*ASP.NET automatically converts the data for you into this object 
    if you post a json object as follows:
{
    "Name": "SomeName",
      "Value": "SomeValue"
}
*/
   //do some stuff
}

Dies hat mir sehr geholfen, als ich in meiner Web-API gearbeitet habe und mein Leben super einfach gemacht hat.

cr1pto
quelle
0
         string json = @"{
            'Name': 'Wide Web',
            'Url': 'www.wideweb.com.br'}";

        JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
        dynamic j = jsonSerializer.Deserialize<dynamic>(json);
        string name = j["Name"].ToString();
        string url = j["Url"].ToString();
Fernando Meneses Gomes
quelle
-1
var result = controller.ActioName(objParams);
IDictionary<string, object> data = (IDictionary<string, object>)new System.Web.Routing.RouteValueDictionary(result.Data);
Assert.AreEqual("Table already exists.", data["Message"]);
Jidheesh Rajan
quelle
2
Sie sollten Ihre Lösung besser erklären, anstatt nur eine Codezeile zu veröffentlichen. Sie können lesen Wie schreibe ich eine gute Antwort .
Massimiliano Kraus
Vergessen Sie nicht, System.Webin Ihre Projektreferenzen aufzunehmen.
Ohad Cohen
-3
 using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(user)))
 {
    // Deserialization from JSON  
    DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(UserListing))
    DataContractJsonSerializer(typeof(UserListing));
    UserListing response = (UserListing)deserializer.ReadObject(ms);

 }

 public class UserListing
 {
    public List<UserList> users { get; set; }      
 }

 public class UserList
 {
    public string FirstName { get; set; }       
    public string LastName { get; set; } 
 }
Kobie Williams
quelle