Newtonsoft를 사용하여 JSON을 .NET 객체로 직렬화 해제 (또는 LINQ to JSON?)


318

Newtonsoft에 대한 몇 가지 게시물이 있다는 것을 알고 있기 때문에 이것이 반복되는 것은 아닙니다 ... 카자 API에서 반환 된 JSON 데이터를 멋진 객체로 변환하려고합니다.

WebClient client = new WebClient();
Stream stream = client.OpenRead("http://api.kazaa.com/api/v1/search.json?q=muse&type=Album");
StreamReader reader = new StreamReader(stream);

List<string> list = Newtonsoft.Json.JsonConvert.DeserializeObject<List<string>>(reader.Read().ToString());

foreach (string item in list)
{
    Console.WriteLine(item);
}

//Console.WriteLine(reader.ReadLine());
stream.Close();

그 JsonConvert 라인은 내가 시도한 가장 최근의 것입니다 ... 나는 그것을 얻지 못하고 당신에게 부탁하여 약간의 발걸음을 없애기를 바라고있었습니다. 원래 그것을 Dictionary 또는 무언가로 변환하려고 시도했습니다 ... 실제로 문서에서 판단 할 때 몇 가지 값을 가져와야합니다 .Newtonsoft의 LINQ to JSON이 더 나은 선택 일 수 있습니까? 생각 / 링크?

다음은 JSON 반환 데이터의 예입니다.

{
  "page": 1,
  "total_pages": 8,
  "total_entries": 74,
  "q": "muse",
  "albums": [
    {
      "name": "Muse",
      "permalink": "Muse",
      "cover_image_url": "http://image.kazaa.com/images/69/01672812 1569/Yaron_Herman_Trio/Muse/Yaron_Herman_Trio-Muse_1.jpg",
      "id": 93098,
      "artist_name": "Yaron Herman Trio"
    },
    {
      "name": "Muse",
      "permalink": "Muse",
      "cover_image_url": "htt p://image.kazaa.com/images/54/888880301154/Candy_Lo/Muse/Candy_Lo-Muse_1.jpg",
      "i d": 102702,
      "artist_name": "\u76e7\u5de7\u97f3"
    },
    {
      "name": "Absolution",
      "permalink": " Absolution",
      "cover_image_url": "http://image.kazaa.com/images/65/093624873365/Mus e/Absolution/Muse-Absolution_1.jpg",
      "id": 48896,
      "artist_name": "Muse"
    },
    {
      "name": "Ab solution",
      "permalink": "Absolution-2",
      "cover_image_url": "http://image.kazaa.com/i mages/20/825646911820/Muse/Absolution/Muse-Absolution_1.jpg",
      "id": 118573,
      "artist _name": "Muse"
    },
    {
      "name": "Black Holes And Revelations",
      "permalink": "Black-Holes-An d-Revelations",
      "cover_image_url": "http://image.kazaa.com/images/66/093624428466/ Muse/Black_Holes_And_Revelations/Muse-Black_Holes_And_Revelations_1.jpg",
      "id": 48813,
      "artist_name": "Muse"
    },
    {
      "name": "Black Holes And Revelations",
      "permalink": "Bla ck-Holes-And-Revelations-2",
      "cover_image_url": "http://image.kazaa.com/images/86/ 825646911486/Muse/Black_Holes_And_Revelations/Muse-Black_Holes_And_Revelations_1 .jpg",
      "id": 118543,
      "artist_name": "Muse"
    },
    {
      "name": "Origin Of Symmetry",
      "permalink": "Origin-Of-Symmetry",
      "cover_image_url": "http://image.kazaa.com/images/29/825646 912629/Muse/Origin_Of_Symmetry/Muse-Origin_Of_Symmetry_1.jpg",
      "id": 120491,
      "artis t_name": "Muse"
    },
    {
      "name": "Showbiz",
      "permalink": "Showbiz",
      "cover_image_url": "http: //image.kazaa.com/images/68/825646182268/Muse/Showbiz/Muse-Showbiz_1.jpg",
      "id": 60444,
      "artist_name": "Muse"
    },
    {
      "name": "Showbiz",
      "permalink": "Showbiz-2",
      "cover_imag e_url": "http://image.kazaa.com/images/50/825646912650/Muse/Showbiz/Muse-Showbiz_ 1.jpg",
      "id": 118545,
      "artist_name": "Muse"
    },
    {
      "name": "The Resistance",
      "permalink": "T he-Resistance",
      "cover_image_url": "http://image.kazaa.com/images/36/825646864836/ Muse/The_Resistance/Muse-The_Resistance_1.jpg",
      "id": 121171,
      "artist_name": "Muse"
    }
  ],
  "per_page": 10
}

나는 더 많은 독서를했고 Newtonsoft의 LINQ to JSON은 WebClient, Stream, StreamReader 및 Newtonsoft를 사용하여 정확히 내가 원하는 것임을 발견했습니다 .JSON 데이터를 위해 Kazaa를 누르고 URL을 추출하고 파일을 다운로드하여 수행 할 수 있습니다 모두 일곱 줄의 코드처럼! 나는 그것을 좋아한다.

WebClient client = new WebClient();
Stream stream = client.OpenRead("http://api.kazaa.com/api/v1/search.json?q=muse&type=Album");
StreamReader reader = new StreamReader(stream);

Newtonsoft.Json.Linq.JObject jObject = Newtonsoft.Json.Linq.JObject.Parse(reader.ReadLine());

// Instead of WriteLine, 2 or 3 lines of code here using WebClient to download the file
Console.WriteLine((string)jObject["albums"][0]["cover_image_url"]);
stream.Close();

이 게시물은 너무 많은 인기를 얻었습니다. 의견에서 논의 된 "사용"비트를 포함하는 것이 도움이 될 것이라고 생각했습니다.

using(var client = new WebClient())
using(var stream = client.OpenRead("http://api.kazaa.com/api/v1/search.json?q=muse&type=Album"))
using (var reader = new StreamReader(stream))
{
    var jObject = Newtonsoft.Json.Linq.JObject.Parse(reader.ReadLine());
    Console.WriteLine((string) jObject["albums"][0]["cover_image_url"]);
}

6
매끄러운 예, 감사합니다. 그냥 제안 : 당신이 간결이 떨어져 왼쪽,하지만 이후 수도 WebClient, Stream그리고 StreamReader모든 구현 IDisposable당신은 몇 가지 추가 할 수 있습니다, using당신의 코드 블록을.
arcain

아 네, 좋은 전화 ... (그래야 실제로 콘솔 응용 프로그램이었습니다. 내가 한 작업을 연구하기 위해 실제로 빠르게 실행되었습니다) 이제 퍼즐의 마지막 조각 인 HLS + AES 암호화를 연구하십시오.) ... lol
J Benjamin

1
+1 Linq 예제를 게시 해 주셔서 감사합니다. 정확히 내가 필요한 것.
Mark Wilkins 2016 년

newtonsoft 솔루션이 JSON을 완전히 직렬화 해제하지 않습니까? @arcain의 솔루션처럼.
AXMIM

: 여기에 링크를 참고 JSON에 LINQ
유 양 지앤

답변:


259

JSON 객체에서 몇 가지 항목을 가져와야 할 경우 Json.NET의 LINQ to JSON JObject클래스를 사용합니다. 예를 들면 다음과 같습니다.

JToken token = JObject.Parse(stringFullOfJson);

int page = (int)token.SelectToken("page");
int totalPages = (int)token.SelectToken("total_pages");

JSON 객체를 완전히 직렬화 해제 할 필요가 없기 때문에이 방법이 마음에 듭니다. 이것은 트위터와 같은 객체 속성이 누락되어 놀라게 할 수있는 API에 유용합니다.

설명서 : Json.NETLINQ를 사용하여 JSON을 Json.NET을 사용하여 JSON으로 직렬화 및 역 직렬화


1
나중에 좀 더 읽기와 테스트를 해봤는데 ... 이것도 좋은 방법이라고 생각했습니다 ... Newtonsoft, 꽤 좋은 도서관, 다른 사람들을 위해 예제를 게시하겠습니다
J Benjamin

1
내가 어떻게하고 있는지에 대한 대략적인 예를 게시했습니다 ... 아주 동일하지는 않습니다 .JToken.Parse를 제안했습니다. 아직 두 가지의 차이점을 알지 못합니다.
J Benjamin

1
@Jbenjamin 감사합니다! 오타였습니다. JToken은 JObject의 기본 클래스이며 더 추상적 인 유형으로 작업하는 것이 개인적으로 선호됩니다. 관심을 가져 주셔서 감사합니다.
arcain

죄송하지만 JToken 또는 JObject 여야합니까? 위의 코드는 여전히 "JsonReader에서 JObject를 읽는 중 오류가 발생했습니다"라는 오류가 계속 발생합니다.
TYRONEMICHAEL

1
@Tyrone 물론, 문제 없습니다. 실제로이 코드를 트위터 상태 구문 분석에도 사용하며 트위터 호출에 대해 약간의 오류 처리가 필요합니다. 아직 그렇게하지 않은 경우 구문 분석을 시도하기 전에 Twitter에서 원시 JSON 응답을 로그로 덤프하는 것이 좋습니다. 그런 다음 실패하면 적어도 전선을 통해 펑키 한 것을 받았는지 확인할 수 있습니다.
arcain

272

C #을 사용할 수 있습니다 dynamic 형식을 사용하면 작업을보다 쉽게 ​​수행 할 수 있습니다. 이 기술은 또한 마술 문자열에 의존하지 않기 때문에 리팩토링을 더 단순하게 만듭니다.

JSON

아래의 JSON 문자열은 HTTP API 호출에서 간단한 반응이며, 그것은 두 가지 속성을 정의 Id하고 Name.

{"Id": 1, "Name": "biofractal"}

씨#

JsonConvert.DeserializeObject<dynamic>()이 문자열을 동적 유형으로 직렬화 해제 한 다음 일반적인 방식으로 해당 특성에 간단히 액세스하는 데 사용하십시오 .

dynamic results = JsonConvert.DeserializeObject<dynamic>(json);
var id = results.Id;
var name= results.Name;

당신의 유형을 지정하는 경우 results변수로 dynamic대신 사용하는 var키워드를, 다음 속성 값이 제대로 예를 들면, 역 직렬화됩니다 Idint아닌JValue (주석 아래에 대한 GFoley83 덕분에).

참고 : Newtonsoft 어셈블리의 NuGet 링크는 http://nuget.org/packages/newtonsoft.json입니다. 입니다.

패키지 : nuget live 설치 프로그램으로 패키지를 추가 할 수도 있습니다. 프로젝트를 열면 패키지를 찾아 설치 한 다음 unistall, update 설치하면 종속성 / NuGet에서 프로젝트에 추가됩니다.


newtonsoft.dll 버전 4.5.6으로 트위터 응답을 deserialize하기 위해 위와 동일한 코드를 사용하고 있었고 ..하지만 버전 5.0.6으로 업데이트 한 후 오류가 발생했습니다. 왜 ??
Pranav

1
우리가 알고 있거나 c # 클래스가있을 때 동적 객체에 좋습니다. 예를 들어 <Myclass>와 같이 동적 대신 C # 클래스로 사용할 수 있습니다.
MSTdev

2
dynamic results = JsonConvert.DeserializeObject<ExpandoObject>(json);FTW를 사용 하십시오. 올바르게 Idint로 deserialize 됩니다 JValue. 여기를 참조하십시오 : dotnetfiddle.net/b0WxGJ
GFoley83

@biofractal dynamic results = JsonConvert.DeserializeObject<dynamic>(json); VB.NET에서 어떻게해야 합니까? Dim results As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(Of Object)(json)작동하지 않습니다.
Flo


41

dynamic키워드를 사용하면 이런 종류의 객체를 파싱하기가 정말 쉬워집니다.

dynamic x = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonString);
var page = x.page;
var total_pages = x.total_pages
var albums = x.albums;
foreach(var album in albums)
{
    var albumName = album.name;

    // Access album data;
}

결과를 반복하는 방법을 알고 싶었습니다. 이걸 찾기에는 너무 오래 걸렸습니다 ... 감사합니다 !!
batoutofhell

22

내가 틀렸다면 정정하십시오. 그러나 이전 예제는 최신 버전의 James Newton의 Json.NET 라이브러리와 약간 일치하지 않는다고 생각합니다.

var o = JObject.Parse(stringFullOfJson);
var page = (int)o["page"];
var totalPages = (int)o["total_pages"];

1
답장을 보내 주셔서 감사합니다. Rick, 나중에 가장 최근의 문서에서 찾은 예제와 비슷합니다.
J Benjamin

1
그래, arcain이 오타를 고쳤으므로 내 의견은 이제 nitpicky처럼 보입니다. '(. JToken.Parse를 인식하지 못했기 때문에 원래 게시했습니다.
Rick Leitch

1
전혀 이질적이지 않습니다-분명히 실수 가 있었고 , 그것을하는 방법은 항상 여러 가지가 있습니다. 그건 그렇고, 내 Json.NET 버전은 on 인덱서를 사용하는 구문을 지원 JObject하지만 내 답변을 위해 수정 한 코드는 SelectToken메소드 의 과부하를 사용하는 코드에서 가져 왔 으므로 토큰이 아닌 경우 예외를 억제 할 수 있습니다 발견 : JToken JToken.SelectToken(string tokenName, bool errorWhenNoMatch), 그래서 자세한 정보가 나온 곳입니다.
arcain

18

나와 같이 강하게 유형이 지정된 객체를 다루는 것을 선호한다면 다음을 수행하십시오.

MyObj obj =  JsonConvert.DeserializeObject<MyObj>(jsonString);

이렇게하면 인텔리전스 및 컴파일 시간 유형 오류 검사를 사용할 수 있습니다.

JSON을 메모리에 복사하고 JSON 객체로 붙여 넣어 필요한 객체를 쉽게 만들 수 있습니다 (Visual Studio-> 편집-> 붙여 넣기 특수-> JSON을 클래스로 붙여 넣기).

여기를 참조 하십시오Visual Studio에 해당 옵션이없는 경우 .

또한 JSON이 유효한지 확인해야합니다. 객체 배열 일 경우 시작시 자신의 객체를 추가하십시오. 즉 { "obj": [{}, {}, {}]}

** 나는 동적 이 때때로 일을 더 쉽게 만든다는 것을 알고 있지만 이것에 대해서는 약간의 문제가 있습니다.


1
프로그래밍에 대해 내가 가장 선호하는 접근 방식은 다음과 같습니다. 나는 강한 타이핑 된 객체를 좋아합니다. 이 코드를 사용하고 수정했기 때문에 감사합니다.
j.hull

11

느슨하게 입력 된 동적 목록 -역 직렬화 및 값 읽기

// First serializing
dynamic collection = new { stud = stud_datatable }; // The stud_datable is the list or data table
string jsonString = JsonConvert.SerializeObject(collection);


// Second Deserializing
dynamic StudList = JsonConvert.DeserializeObject(jsonString);

var stud = StudList.stud;
foreach (var detail in stud)
{
    var Address = detail["stud_address"]; // Access Address data;
}

8

나는이 방법을 좋아한다 :

using Newtonsoft.Json.Linq;
// jsonString is your JSON-formatted string
JObject jsonObj = JObject.Parse(jsonString);
Dictionary<string, object> dictObj = jsonObj.ToObject<Dictionary<string, object>>();

이제 dictObj사전으로 사용하여 원하는 모든 것에 액세스 할 수 있습니다 . Dictionary<string, string>값을 문자열로 얻는 것을 선호 하는 경우 에도 사용할 수 있습니다 .

이 동일한 방법을 사용하여 모든 종류의 .NET 객체로 캐스트 할 수 있습니다.


2
나는이 방법이 두 가지 이유로 매우 훌륭하다는 것을 알았습니다 : 1) 데이터 유형에 관심이 없을 때 (모든 것이 문자열 임), 2) 값의 사전으로 작업하는 것이 편리합니다
netfed

7

또한 JSON 콘텐츠 내에 중첩 된 특정 값을 찾고 있다면 다음과 같이 할 수 있습니다.

yourJObject.GetValue("jsonObjectName").Value<string>("jsonPropertyName");

그리고 거기서부터.

전체 JSON을 C # 객체로 변환하는 비용을 부담하지 않으려는 경우 도움이 될 수 있습니다.


2

json에 대한 Extionclass를 얻었습니다.

 public static class JsonExtentions
    {
        public static string SerializeToJson(this object SourceObject) { return Newtonsoft.Json.JsonConvert.SerializeObject(SourceObject); }


        public static T JsonToObject<T>(this string JsonString) { return (T)Newtonsoft.Json.JsonConvert.DeserializeObject<T>(JsonString); }
}

디자인 패턴:

 public class Myobject
    {
        public Myobject(){}
        public string prop1 { get; set; }

        public static Myobject  GetObject(string JsonString){return  JsonExtentions.JsonToObject<Myobject>(JsonString);}
        public  string ToJson(string JsonString){return JsonExtentions.SerializeToJson(this);}
    }

용법:

   Myobject dd= Myobject.GetObject(jsonstring);

                 Console.WriteLine(dd.prop1);


1

이 파티에 상당히 늦었지만 오늘 직장에서이 문제를 직접 만났습니다. 다음은이 문제를 해결 한 방법입니다.

도서 목록을 검색하기 위해 타사 API에 액세스하고있었습니다. 이 객체는 대략 20 개 이상의 필드를 포함하는 방대한 JSON 객체를 반환했으며 그 중 ID 만 List 문자열 객체로 필요했습니다. 동적 객체에서 linq를 사용하여 필요한 특정 필드를 검색 한 다음 List 문자열 객체에 삽입했습니다.

dynamic content = JsonConvert.DeserializeObject(requestContent);
var contentCodes = ((IEnumerable<dynamic>)content).Where(p => p._id != null).Select(p=>p._id).ToList();

List<string> codes = new List<string>();

foreach (var code in contentCodes)
{
    codes.Add(code?.ToString());
}

0

마지막으로 JSON에서 상태 이름 가져 오기

감사합니다!

Imports System
Imports System.Text
Imports System.IO
Imports System.Net
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Imports System.collections.generic

Public Module Module1
    Public Sub Main()

         Dim url As String = "http://maps.google.com/maps/api/geocode/json&address=attur+salem&sensor=false"
            Dim request As WebRequest = WebRequest.Create(url)
        dim response As WebResponse = DirectCast(request.GetResponse(), HttpWebResponse)
        dim reader As New StreamReader(response.GetResponseStream(), Encoding.UTF8)
          Dim dataString As String = reader.ReadToEnd()

        Dim getResponse As JObject = JObject.Parse(dataString)

        Dim dictObj As Dictionary(Of String, Object) = getResponse.ToObject(Of Dictionary(Of String, Object))()
        'Get State Name
        Console.WriteLine(CStr(dictObj("results")(0)("address_components")(2)("long_name")))
    End Sub
End Module
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.