Konwertuj ciąg JSON na obiekt C #

183

Próba konwersji ciągu JSON na obiekt w C #. Za pomocą bardzo prostego przypadku testowego:

JavaScriptSerializer json_serializer = new JavaScriptSerializer();
object routes_list = json_serializer.DeserializeObject("{ \"test\":\"some data\" }");

Problem polega na tym, że lista tras nigdy nie jest ustawiana; to niezdefiniowany obiekt. Jakieś pomysły?

Justin
źródło
1
@Greg: Właściwie polecam JavaScriptSerializerwersję MS, ponieważ nie akceptuje nic poza niestandardowym formatowaniem JSON w WCF (np. Pola daty, które wyglądają jak daty, ale nie są otoczone DATE () źle zawodzą)
Brad Christie
Spójrz także na ten obiekt Parsing JSON z JavascriptSerializer w artykule .NET , który jest naprawdę świetnym tutorialem.
scatmoi
Skąd bierzesz JavaScriptSerializer? Jest nierozpoznany w moim projekcie C # .NET 3.5.
B. Clay Shannon
1
@B. Clay Shannon To rozwiązało dla mnie stackoverflow.com/questions/7000811/…
Fuzzybear

Odpowiedzi:

127

Wygląda na to, że próbujesz deserializować do surowego obiektu. Możesz utworzyć klasę reprezentującą obiekt, na który konwertujesz. Byłoby to najbardziej przydatne w przypadkach, gdy masz do czynienia z większymi obiektami lub ciągami JSON.

Na przykład:

  class Test {

      String test; 

      String getTest() { return test; }
      void setTest(String test) { this.test = test; }

  }

Twój kod deserializacji to:

   JavaScriptSerializer json_serializer = new JavaScriptSerializer();
   Test routes_list = 
          (Test)json_serializer.DeserializeObject("{ \"test\":\"some data\" }");

Więcej informacji można znaleźć w tym samouczku: http://www.codeproject.com/Tips/79435/Deserialize-JSON-with-Csharp.aspx

jmort253
źródło
1
Ale w wskazanym artykule stosuje się właściwości automatyczne. Warto też wspomnieć.
Ivan Kochurkin
11
Przepraszamy, ale ten przykładowy kod nie działa. DeserializeObject daje wyjątek. Użyj var tras_list = serializer.Deserialize <Test> ("{\" test \ ": \" some data \ "}"); zamiast. Ponadto nie potrzebujesz get / setTest (), a test ciągów powinien być publiczny. To bardziej przypomina Javę niż C #.
dvallejo
jak wspomniał Dan Vallejo, jest to nieprawidłowe rozwiązanie. W końcu setTest (test ciągu) nie zwraca, co również jest błędem kompilacji.
Payam
1
Można również użyć tego: json_serializer.Deserialize <Test> ("{\" test \ ": \" some data \ "}"); // zamiast (Test) json_serializer .....
Bashar Abu Shamaa
1
Jeśli nie masz pewności co do formatu obiektu klasy, wypróbuj ten link . To przekłada łańcuch Jsona na odpowiednie klasy. Zaoszczędził mi mnóstwo czasu!
jade290
231

Lub możesz użyć biblioteki Newtownsoft.Json w następujący sposób:

using Newtonsoft.Json;
...
var result = JsonConvert.DeserializeObject<T>(json);

Gdzie Tjest typ obiektu, który pasuje do ciągu JSON.

tripletdad99
źródło
3
To takie proste i tak długo zastanawiałem się, jak to zrobić.
maracuja-juice
58

Prawdopodobnie nie chcesz po prostu deklarować listy tras jako objecttypu. Nie ma właściwości .test, więc naprawdę nie odzyskasz ładnego obiektu. Jest to jedno z tych miejsc, w których lepiej byłoby zdefiniować klasę lub strukturę lub skorzystać z dynamicznego słowa kluczowego.

Jeśli naprawdę chcesz, aby ten kod działał tak, jak go masz, musisz wiedzieć, że obiekt zwrócony przez DeserializeObject jest ogólnym słownikiem ciągów znaków, obiekt. Oto kod, aby to zrobić w ten sposób:

var json_serializer = new JavaScriptSerializer();
var routes_list = (IDictionary<string, object>)json_serializer.DeserializeObject("{ \"test\":\"some data\" }");
Console.WriteLine(routes_list["test"]);

Jeśli chcesz użyć dynamicznego słowa kluczowego, możesz przeczytać tutaj .

Jeśli zadeklarujesz klasę lub strukturę, możesz wywołać Deserialize zamiast DeserializeObject w następujący sposób:

class MyProgram {
    struct MyObj {
        public string test { get; set; }
    }

    static void Main(string[] args) {
        var json_serializer = new JavaScriptSerializer();
        MyObj routes_list = json_serializer.Deserialize<MyObj>("{ \"test\":\"some data\" }");
        Console.WriteLine(routes_list.test);

        Console.WriteLine("Done...");
        Console.ReadKey(true);
    }
}
mattmc3
źródło
Wykonanie: json_serializer = new JavaScriptSerializer (); obiekt trasy_list = (IDictionary <string, object>) json_serializer.DeserializeObject ("{\" test \ ": \" niektóre dane tutaj \ "}"); Nadal pobieranie „tras_list” nie istnieje w bieżącym kontekście.
Justin
1
Nie używać object routes_list. Użyj varlub jawnie powtórz się i zadeklaruj listę tras jako IDictionary <ciąg, obiekt>.
mattmc3
31

Używanie obiektu dynamicznego z JavaScriptSerializer.

JavaScriptSerializer serializer = new JavaScriptSerializer(); 
dynamic item = serializer.Deserialize<object>("{ \"test\":\"some data\" }");
string test= item["test"];

//test Result = "some data"
İbrahim Özbölük
źródło
19

Newtonsoft jest szybszy niż serializator skryptów Java. ... ten zależy od pakietu Newtonsoft NuGet, który jest popularny i lepszy niż domyślny serializator.

rozwiązanie z jednym kodem linii.

var myclass = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(Jsonstring);

Myclass oMyclass = Newtonsoft.Json.JsonConvert.DeserializeObject<Myclass>(Jsonstring);
MSTdev
źródło
15

Oto prosta klasa, którą zebrałem z różnych postów ... Testowano ją przez około 15 minut, ale wydaje się, że działa dla moich celów. Służy JavascriptSerializerdo wykonywania pracy, do której można się odwoływać w aplikacji, korzystając z informacji wyszczególnionych w tym poście .

Poniższy kod można uruchomić w LinqPad, aby go przetestować:

  • Kliknij prawym przyciskiem myszy kartę skryptu w LinqPad i wybierz „Właściwości zapytania”
  • Odwoływanie się do „System.Web.Extensions.dll” w „Dodatkowych odnośnikach”
  • Dodanie „dodatkowych importów przestrzeni nazw” w „System.Web.Script.Serialization”.

Mam nadzieję, że to pomoże!

void Main()
{
  string json = @"
  {
    'glossary': 
    {
      'title': 'example glossary',
        'GlossDiv': 
        {
          'title': 'S',
          'GlossList': 
          {
            'GlossEntry': 
            {
              'ID': 'SGML',
              'ItemNumber': 2,          
              'SortAs': 'SGML',
              'GlossTerm': 'Standard Generalized Markup Language',
              'Acronym': 'SGML',
              'Abbrev': 'ISO 8879:1986',
              'GlossDef': 
              {
                'para': 'A meta-markup language, used to create markup languages such as DocBook.',
                'GlossSeeAlso': ['GML', 'XML']
              },
              'GlossSee': 'markup'
            }
          }
        }
    }
  }

  ";

  var d = new JsonDeserializer(json);
  d.GetString("glossary.title").Dump();
  d.GetString("glossary.GlossDiv.title").Dump();  
  d.GetString("glossary.GlossDiv.GlossList.GlossEntry.ID").Dump();  
  d.GetInt("glossary.GlossDiv.GlossList.GlossEntry.ItemNumber").Dump();    
  d.GetObject("glossary.GlossDiv.GlossList.GlossEntry.GlossDef").Dump();   
  d.GetObject("glossary.GlossDiv.GlossList.GlossEntry.GlossDef.GlossSeeAlso").Dump(); 
  d.GetObject("Some Path That Doesnt Exist.Or.Another").Dump();   
}


// Define other methods and classes here

public class JsonDeserializer
{
  private IDictionary<string, object> jsonData { get; set; }

  public JsonDeserializer(string json)
  {
    var json_serializer = new JavaScriptSerializer();

    jsonData = (IDictionary<string, object>)json_serializer.DeserializeObject(json);
  }

  public string GetString(string path)
  {
    return (string) GetObject(path);
  }

  public int? GetInt(string path)
  {
    int? result = null;

    object o = GetObject(path);
    if (o == null)
    {
      return result;
    }

    if (o is string)
    {
      result = Int32.Parse((string)o);
    }
    else
    {
      result = (Int32) o;
    }

    return result;
  }

  public object GetObject(string path)
  {
    object result = null;

    var curr = jsonData;
    var paths = path.Split('.');
    var pathCount = paths.Count();

    try
    {
      for (int i = 0; i < pathCount; i++)
      {
        var key = paths[i];
        if (i == (pathCount - 1))
        {
          result = curr[key];
        }
        else
        {
          curr = (IDictionary<string, object>)curr[key];
        }
      }
    }
    catch
    {
      // Probably means an invalid path (ie object doesn't exist)
    }

    return result;
  }
}
Brad Parks
źródło
14

Możesz łatwo spełnić swoje wymagania, korzystając z biblioteki Newtonsoft.Json. Piszę jeden przykład poniżej, spójrz na to.

Klasa dla rodzaju otrzymywanego obiektu:

public class User
{
    public int ID { get; set; }
    public string Name { get; set; }

}

Kod:

static void Main(string[] args)
{

      string json = "{\"ID\": 1, \"Name\": \"Abdullah\"}";

      User user = JsonConvert.DeserializeObject<User>(json);

      Console.ReadKey();
}

jest to bardzo prosty sposób na parsowanie twojego Jsona.

Mirza Danish Baig
źródło
11

Jak powiedział tripletdad99

var result = JsonConvert.DeserializeObject<T>(json);

ale jeśli nie chcesz, aby utworzyć dodatkowy przedmiot można zrobić to z Dictionaryzamiast

var result = JsonConvert.DeserializeObject<Dictionary<string, string>>(json_serializer);
stanimirsp
źródło
Jest to przydatne, gdy następnie przekazujesz parametry do Url.Action (akcja, kontroler, wynik)
Lapenkov Vladimir
8

dodaj ten plik ddl do odwołania do projektu: System.Web.Extensions.dll

użyj tej przestrzeni nazw: using System.Web.Script.Serialization;

public class IdName
{
    public int Id { get; set; }
    public string Name { get; set; }
}


   string jsonStringSingle = "{'Id': 1, 'Name':'Thulasi Ram.S'}".Replace("'", "\"");
   var entity = new JavaScriptSerializer().Deserialize<IdName>(jsonStringSingle);

   string jsonStringCollection = "[{'Id': 2, 'Name':'Thulasi Ram.S'},{'Id': 2, 'Name':'Raja Ram.S'},{'Id': 3, 'Name':'Ram.S'}]".Replace("'", "\"");
   var collection = new JavaScriptSerializer().Deserialize<IEnumerable<IdName>>(jsonStringCollection);
Thulasiram
źródło
6

Skopiuj Jsona i wklej w polu tekstowym na json2csharp i kliknij przycisk Generuj.

Zostanie wygenerowana klasa cs przy użyciu tego pliku cs jak poniżej

var generatedcsResponce = JsonConvert.DeserializeObject(yourJson);

Gdzie RootObjectjest nazwa wygenerowanego pliku cs ;

islam
źródło
4

Innym szybkim i łatwym sposobem na częściową automatyzację tych kroków jest:

  1. weź JSON, który chcesz przeanalizować i wklej go tutaj: https://app.quicktype.io/ . Zmień język na C # w menu rozwijanym.
  2. Zaktualizuj nazwę w lewym górnym rogu do nazwy swojej klasy, domyślnie „Witamy”.
  3. W Visual Studio przejdź do strony WWW -> Zarządzaj pakietami i użyj NuGet, aby dodać Json.Net z Newtonsoft.
  4. app.quicktype.io wygenerował metody serializacji w oparciu o Newtonsoft. Alternatywnie możesz teraz użyć kodu takiego jak:

    Klient WebClient = nowy WebClient ();

    ciąg myJSON = client.DownloadString („ https://URL_FOR_JSON.com/JSON_STUFF ”);

    var myClass = Newtonsoft.Json.JsonConvert.DeserializeObject (myJSON);

Jason Hitchings
źródło
Link nie jest już ważny
Myles J
Dzięki Myles J zaktualizowałem do nowej witryny, która wydaje się działać dobrze.
Jason Hitchings
0

Konwertuj ciąg JSON na obiekt w C #. Za pomocą poniższego przypadku testowego .. to zadziałało dla mnie. Tutaj „ MenuInfo ” to mój obiekt klasy C #.

JsonTextReader reader = null;
try
{
    WebClient webClient = new WebClient();
    JObject result = JObject.Parse(webClient.DownloadString("YOUR URL"));
    reader = new JsonTextReader(new System.IO.StringReader(result.ToString()));
    reader.SupportMultipleContent = true;
}
catch(Exception)
{}

JsonSerializer serializer = new JsonSerializer();
MenuInfo menuInfo = serializer.Deserialize<MenuInfo>(reader);
Bhaskar
źródło
0

Najpierw musisz dołączyć bibliotekę:

using System.Runtime.Serialization.Json;

DataContractJsonSerializer desc = new DataContractJsonSerializer(typeof(BlogSite));
string json = "{\"Description\":\"Share knowledge\",\"Name\":\"zahid\"}";

using (var ms = new MemoryStream(ASCIIEncoding.ASCII.GetBytes(json)))
{
    BlogSite b = (BlogSite)desc.ReadObject(ms);
    Console.WriteLine(b.Name);
    Console.WriteLine(b.Description);
}
Muhammad Zahid
źródło