Jak przekształcić obiekt C # w ciąg JSON w .NET?

943

Mam takie zajęcia:

class MyDate
{
    int year, month, day;
}

class Lad
{
    string firstName;
    string lastName;
    MyDate dateOfBirth;
}

I chciałbym przekształcić Ladobiekt w ciąg JSON w następujący sposób:

{
    "firstName":"Markoff",
    "lastName":"Chaney",
    "dateOfBirth":
    {
        "year":"1901",
        "month":"4",
        "day":"30"
    }
}

(bez formatowania). Znalazłem ten link , ale używa przestrzeni nazw, która nie jest w .NET 4 . Słyszałem także o JSON.NET , ale ich witryna wydaje się w tej chwili niedostępna i nie chcę używać zewnętrznych plików DLL.

Czy istnieją inne opcje oprócz ręcznego tworzenia modułu zapisującego ciąg JSON ?

Hui
źródło
2
JSON.net można załadować tutaj Innym i szybszym (jak mówią - nie testowałem go osobiście) rozwiązaniem jest ServiceStack.Text Nie polecam zwijania własnego parsera JSON. Prawdopodobnie będzie wolniejszy i bardziej podatny na błędy lub będziesz musiał zainwestować dużo czasu.
Zebi
tak. C # ma typ o nazwie JavaScriptSerializer
Glenn Ferrie
możliwy duplikat Generics / JSON JavaScriptSerializer C #
Filip Ekberg
2
Hm .. o ile widzę, powinieneś być w stanie użyć: msdn.microsoft.com/en-us/library/... Który jest również w .Net 4.0 zgodnie ze stroną MSDN. Powinieneś być w stanie korzystać z metody Serialize (Object obj): msdn.microsoft.com/en-us/library/bb292287.aspx Czy coś tu brakuje? Btw. link wydaje się być kodem, a nie linkiem
Holger
Nie wspominając o tym, że nie ma żadnych zależności od przestrzeni nazw System.Web.Xyz ...
Dave Jellison

Odpowiedzi:

897

Możesz użyć JavaScriptSerializerklasy (dodaj odniesienie do System.Web.Extensions):

using System.Web.Script.Serialization;
var json = new JavaScriptSerializer().Serialize(obj);

Pełny przykład:

using System;
using System.Web.Script.Serialization;

public class MyDate
{
    public int year;
    public int month;
    public int day;
}

public class Lad
{
    public string firstName;
    public string lastName;
    public MyDate dateOfBirth;
}

class Program
{
    static void Main()
    {
        var obj = new Lad
        {
            firstName = "Markoff",
            lastName = "Chaney",
            dateOfBirth = new MyDate
            {
                year = 1901,
                month = 4,
                day = 30
            }
        };
        var json = new JavaScriptSerializer().Serialize(obj);
        Console.WriteLine(json);
    }
}
Darin Dimitrov
źródło
95
Należy pamiętać, że Microsoft sugeruje użycie JSON.net zamiast tego rozwiązania. Myślę, że ta odpowiedź stała się nieodpowiednia. Spójrz na odpowiedź willsteel. Źródło: https://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx .
rzelek
9
@DarinDimitrov należy rozważyć dodanie podpowiedzi na temat JSON.net. Microsoft zaleca to zamiast JavascriptSerializer: msdn.microsoft.com/en-us/library/... Możesz także dodać wskazówkę do msdn.microsoft.com/en-us/library/... która jest podejściem obejmującym framework
Mafii
tutaj jest narzędzie online do konwersji classesna jsonformat, mam nadzieję, że ktoś komuś pomoże.
shaijut
6
Dlaczego Microsoft poleciłby rozwiązanie niezależne od swojego? Ich brzmienie jest również bardzo dziwne: „Json.NET powinien być używany do serializacji i deserializacji. Zapewnia funkcje serializacji i deserializacji dla aplikacji obsługujących AJAX.”
Protektor jeden
1
Tylko jeden na głowę, aby nawiązać System.Web.Extensions, musisz mieć ASP.NET AJAX 1.0lub ASP.NET 3.5zainstalować w systemie. Proszę zobaczyć ten stackoverflow.com/questions/7723489/…
Sisir
1054

Ponieważ wszyscy kochamy jednowarstwowe

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

Newtonsoft.Json.JsonConvert.SerializeObject(new {foo = "bar"})

Dokumentacja: Serializacja i deserializacja JSON

mschmoock
źródło
134
Serializator Newtonsoft jest o wiele szybszy i można go dostosowywać, a następnie wbudować. Bardzo polecam go używać. Dzięki za odpowiedź @willsteel
Andrei
8
@JosefPfleger cena dotyczy schematu JSON.NET, a nie JSON.NET regularnego serializatora, którym jest MIT
David Cumps
1
Moje testy wykazały, że Newtonsoft jest wolniejszy niż klasa JavaScriptSerializer. (.NET 4.5.2)
nemke
31
Jeśli czytasz dokumentację MSDN dla JavaScriptSerializer , oczywiste jest, że użyj JSON.net.
dsghi,
3
@JosefPfleger Newtionsoft JSON.net ma licencję MIT ... możesz wprowadzać modyfikacje i odsprzedawać je tak, jak chcesz. Ich strona z cenami dotyczy komercyjnego wsparcia technicznego i niektórych weryfikatorów schematów.
cb88,
95

Użyj biblioteki Json.Net , którą możesz pobrać z Nuget Packet Manager.

Serializacja do ciągu Json:

 var obj = new Lad
        {
            firstName = "Markoff",
            lastName = "Chaney",
            dateOfBirth = new MyDate
            {
                year = 1901,
                month = 4,
                day = 30
            }
        };

var jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(obj);

Deserializowanie do obiektu:

var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<Lad>(jsonString );
Gokulan PH
źródło
57

Użyj DataContractJsonSerializerklasy: MSDN1 , MSDN2 .

Mój przykład: TUTAJ .

W przeciwieństwie do tego może również bezpiecznie deserializować obiekty z ciągu JSON JavaScriptSerializer. Ale osobiście nadal wolę Json.NET .

Edgar
źródło
1
Nadal nie widzę żadnych przykładów na tej stronie , ale oto niektóre na MSDN i gdzie indziej -> ten ostatni używa metod rozszerzeń, aby uzyskać jednolinijki.
Cristian Diaconescu
Och, brakowało mi drugiego łącza MSDN :)
Cristian Diaconescu,
2
Nie serializuje zwykłych klas. Wystąpił błąd „Rozważ zaznaczenie go za pomocą atrybutu DataContractAttribute i zaznaczenie wszystkich jego członków, których chcesz serializować za pomocą atrybutu DataMemberAttribute. Jeśli typ jest kolekcją, rozważ oznaczenie go za pomocą CollectionDataContractAttribute”.
Michael Freidgeim
@MichaelFreidgeim Zgadza się, musisz zaznaczyć właściwości w klasie, którą chcesz serializować za pomocą atrybutów. DataContractAttribute DataMemberAttribute
Edgar
1
@MichaelFreidgeim Co jest lepsze, zależy od wymagań. Atrybuty pozwalają skonfigurować sposób serializacji właściwości.
Edgar
24

Możesz to osiągnąć za pomocą Newtonsoft.json. Zainstaluj Newtonsoft.json z NuGet. I wtedy:

using Newtonsoft.Json;

var jsonString = JsonConvert.SerializeObject(obj);
Waleed Naveed
źródło
22

Wooou! Naprawdę lepiej przy użyciu frameworka JSON :)

Oto mój przykład przy użyciu Json.NET ( http://james.newtonking.com/json ):

using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
using System.IO;

namespace com.blogspot.jeanjmichel.jsontest.model
{
    public class Contact
    {
        private Int64 id;
        private String name;
        List<Address> addresses;

        public Int64 Id
        {
            set { this.id = value; }
            get { return this.id; }
        }

        public String Name
        {
            set { this.name = value; }
            get { return this.name; }
        }

        public List<Address> Addresses
        {
            set { this.addresses = value; }
            get { return this.addresses; }
        }

        public String ToJSONRepresentation()
        {
            StringBuilder sb = new StringBuilder();
            JsonWriter jw = new JsonTextWriter(new StringWriter(sb));

            jw.Formatting = Formatting.Indented;
            jw.WriteStartObject();
            jw.WritePropertyName("id");
            jw.WriteValue(this.Id);
            jw.WritePropertyName("name");
            jw.WriteValue(this.Name);

            jw.WritePropertyName("addresses");
            jw.WriteStartArray();

            int i;
            i = 0;

            for (i = 0; i < addresses.Count; i++)
            {
                jw.WriteStartObject();
                jw.WritePropertyName("id");
                jw.WriteValue(addresses[i].Id);
                jw.WritePropertyName("streetAddress");
                jw.WriteValue(addresses[i].StreetAddress);
                jw.WritePropertyName("complement");
                jw.WriteValue(addresses[i].Complement);
                jw.WritePropertyName("city");
                jw.WriteValue(addresses[i].City);
                jw.WritePropertyName("province");
                jw.WriteValue(addresses[i].Province);
                jw.WritePropertyName("country");
                jw.WriteValue(addresses[i].Country);
                jw.WritePropertyName("postalCode");
                jw.WriteValue(addresses[i].PostalCode);
                jw.WriteEndObject();
            }

            jw.WriteEndArray();

            jw.WriteEndObject();

            return sb.ToString();
        }

        public Contact()
        {
        }

        public Contact(Int64 id, String personName, List<Address> addresses)
        {
            this.id = id;
            this.name = personName;
            this.addresses = addresses;
        }

        public Contact(String JSONRepresentation)
        {
            //To do
        }
    }
}

Test:

using System;
using System.Collections.Generic;
using com.blogspot.jeanjmichel.jsontest.model;

namespace com.blogspot.jeanjmichel.jsontest.main
{
    public class Program
    {
        static void Main(string[] args)
        {
            List<Address> addresses = new List<Address>();
            addresses.Add(new Address(1, "Rua Dr. Fernandes Coelho, 85", "15º andar", "São Paulo", "São Paulo", "Brazil", "05423040"));
            addresses.Add(new Address(2, "Avenida Senador Teotônio Vilela, 241", null, "São Paulo", "São Paulo", "Brazil", null));

            Contact contact = new Contact(1, "Ayrton Senna", addresses);

            Console.WriteLine(contact.ToJSONRepresentation());
            Console.ReadKey();
        }
    }
}

Wynik:

{
  "id": 1,
  "name": "Ayrton Senna",
  "addresses": [
    {
      "id": 1,
      "streetAddress": "Rua Dr. Fernandes Coelho, 85",
      "complement": "15º andar",
      "city": "São Paulo",
      "province": "São Paulo",
      "country": "Brazil",
      "postalCode": "05423040"
    },
    {
      "id": 2,
      "streetAddress": "Avenida Senador Teotônio Vilela, 241",
      "complement": null,
      "city": "São Paulo",
      "province": "São Paulo",
      "country": "Brazil",
      "postalCode": null
    }
  ]
}

Teraz zaimplementuję metodę konstruktora, która otrzyma ciąg JSON i zapełni pola klasy.

Jean J. Michel
źródło
1
Dobry post, to najnowszy sposób na zrobienie tego.
MatthewD
20

Nowy serializator JSON jest dostępny w System.Text.Jsonprzestrzeni nazw. Jest zawarty we wspólnym środowisku .NET Core 3.0 i jest w pakiecie NuGet dla projektów ukierunkowanych na .NET Standard lub .NET Framework lub .NET Core 2.x.

Przykładowy kod:

using System;
using System.Text.Json;

public class MyDate
{
    public int year { get; set; }
    public int month { get; set; }
    public int day { get; set; }
}

public class Lad
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public MyDate DateOfBirth { get; set; }
}

class Program
{
    static void Main()
    {
        var lad = new Lad
        {
            FirstName = "Markoff",
            LastName = "Chaney",
            DateOfBirth = new MyDate
            {
                year = 1901,
                month = 4,
                day = 30
            }
        };
        var json = JsonSerializer.Serialize(lad);
        Console.WriteLine(json);
    }
}

W tym przykładzie klasy, które mają być serializowane, mają raczej właściwości niż pola; System.Text.Jsonserializer obecnie nie szeregować pól.

Dokumentacja:

tdykstra
źródło
9

Jeśli nie są bardzo duże, to prawdopodobnie twoja sprawa eksportuje je jako JSON.

Dzięki temu jest przenośny na wszystkie platformy.

using Newtonsoft.Json;

[TestMethod]
public void ExportJson()
{
    double[,] b = new double[,]
        {
            { 110,  120,  130,  140, 150 },
            {1110, 1120, 1130, 1140, 1150},
            {1000,    1,   5,     9, 1000},
            {1110,    2,   6,    10, 1110},
            {1220,    3,   7,    11, 1220},
            {1330,    4,   8,    12, 1330}
        };

    string jsonStr = JsonConvert.SerializeObject(b);

    Console.WriteLine(jsonStr);

    string path = "X:\\Programming\\workspaceEclipse\\PyTutorials\\src\\tensorflow_tutorials\\export.txt";

    File.WriteAllText(path, jsonStr);
}
użytkownik8426627
źródło
8

Jeśli korzystasz z kontrolera sieci ASP.NET MVC, jest to tak proste, jak:

string ladAsJson = Json(Lad);

Nie mogę uwierzyć, że nikt o tym nie wspominał.

micahhoover
źródło
1
Pojawia się błąd związany z niemożnością rzutowania jsonresult na string.
csga5000,
Skompiluje się z niejawnym pisaniem: var ladAsJson = Json (Lad).
ewomack
3

Głosowałbym na Serializer JSON firmy ServiceStack:

using ServiceStack.Text

string jsonString = new { FirstName = "James" }.ToJson();

Jest to również najszybszy serializator JSON dostępny dla platformy .NET: http://www.servicestack.net/benchmarks/

James
źródło
4
To są bardzo stare standardy. Właśnie przetestowałem wszystkie trzy aktualne wersje Newtonsoft, ServiceStack i JavaScriptSerializer i obecnie Newtonsoft jest najszybszy. Wszyscy oni robią dość szybko.
Michael Logutov
1
ServiceStack nie wydaje się być darmowy.
joelnet,
@joelnet tak jest teraz, ale był darmowy, odpowiadając na pytanie. Jest jednak bezpłatny dla małych witryn i nadal go używam, mimo że jest płatny, jest to świetna platforma.
James
Niektóre testy porównawcze tutaj, choć nie istnieje sama serializacja: docs.servicestack.net/real-world-performance
JohnLBevan
3

Użyj poniższego kodu do konwersji XML na JSON.

var json = new JavaScriptSerializer().Serialize(obj);
Hithesh
źródło
3

Użyj tych narzędzi do wygenerowania klasy C #, a następnie użyj tego kodu do serializacji obiektu:

 var json = new JavaScriptSerializer().Serialize(obj);
Artem Polishchuk
źródło
3

Jest to tak proste (działa również w przypadku obiektów dynamicznych (obiekt typu)):

string json = new
System.Web.Script.Serialization.JavaScriptSerializer().Serialize(MYOBJECT);
MarzSocks
źródło
w sieci nie ma domyślnego skryptu. :(
M o
Szukasz tego: msdn.microsoft.com/en-us/library/...
MarzSocks
Próbowałem tego, ale nie. Skrypt Chyba powinienem dodać go jako odniesienie. Wielkie dzięki
M na
0

Serializer

 public static void WriteToJsonFile<T>(string filePath, T objectToWrite, bool append = false) where T : new()
{
        var contentsToWriteToFile = JsonConvert.SerializeObject(objectToWrite, new JsonSerializerSettings
        {
            Formatting = Formatting.Indented,
        });
        using (var writer = new StreamWriter(filePath, append))
        {
            writer.Write(contentsToWriteToFile);
        }
}

Obiekt

namespace MyConfig
{
    public class AppConfigurationSettings
    {
        public AppConfigurationSettings()
        {
            /* initialize the object if you want to output a new document
             * for use as a template or default settings possibly when 
             * an app is started.
             */
            if (AppSettings == null) { AppSettings=new AppSettings();}
        }

        public AppSettings AppSettings { get; set; }
    }

    public class AppSettings
    {
        public bool DebugMode { get; set; } = false;
    }
}

Realizacja

var jsonObject = new AppConfigurationSettings();
WriteToJsonFile<AppConfigurationSettings>(file.FullName, jsonObject);

Wynik

{
  "AppSettings": {
    "DebugMode": false
  }
}
dynamiclynk
źródło