JSON 콘텐츠를 C # 4 동적 유형으로 역 직렬화하는 방법이 있습니까? 를 사용하기 위해 많은 클래스를 만드는 것을 건너 뛰는 것이 좋습니다 DataContractJsonSerializer
.
JSON 콘텐츠를 C # 4 동적 유형으로 역 직렬화하는 방법이 있습니까? 를 사용하기 위해 많은 클래스를 만드는 것을 건너 뛰는 것이 좋습니다 DataContractJsonSerializer
.
답변:
System.Web.Helpers
어셈블리에 의존하고 싶다면 다음 Json
클래스를 사용할 수 있습니다 .
dynamic data = Json.Decode(json);
MVC 프레임 워크 에는 .NET 4 프레임 워크에 대한 추가 다운로드 로 포함되어 있습니다 . 도움이된다면 Vlad에게 공감대를 제공하십시오! 그러나 클라이언트 환경에이 DLL이 있다고 가정 할 수 없으면 계속 읽으십시오.
대체 직렬화 해제 방법이 여기 에 제안 됩니다 . 버그를 수정하고 코딩 스타일에 맞게 코드를 약간 수정했습니다. 이 코드와 System.Web.Extensions
프로젝트에 대한 참조 만 있으면 됩니다.
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
}
다음과 같이 사용할 수 있습니다.
string json = ...;
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
dynamic obj = serializer.Deserialize(json, typeof(object));
따라서 JSON 문자열이 주어집니다.
{
"Items":[
{ "Name":"Apple", "Price":12.3 },
{ "Name":"Grape", "Price":3.21 }
],
"Date":"21/11/2010"
}
다음 코드는 런타임에 작동합니다.
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)
params
(C #의 키워드) 과 동일한 문제가있었습니다 . 또한을 TryGetMember
재정의 TryGetIndex
하면 JS에서와 동일한 동작을 제공합니다. 그런 다음 어색한 필드 이름을 사용 obj["params"]
하거나 수행 할 수 있습니다 obj["background-color"]
.
dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");
string name = stuff.Name;
string address = stuff.Address.City;
또한 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;
설명서 : 동적으로 JSON 쿼리
stuff
다음과 같이하십시오 :foreach (Newtonsoft.Json.Linq.JProperty jproperty in stuff) { Console.WriteLine("jproperty.Name = {0}", jproperty.Name);}
async
메서드 내부로 문제를 좁혔습니다 . 메소드를 동기식으로 만들면 예상대로 작동합니다. 그러나 메서드 async
를 만들고을 얻을 수 없으며dynamic
단지을 얻습니다 object
. 명시 적 캐스팅은 아무것도하지 않지만 여전히 나에게 object
. 다른 사람이 이것을 경험하고 있습니까?
System.Web.Helpers.Json을 사용 하여이 작업을 수행 할 수 있습니다 .Decode 메서드는 원하는대로 통과 할 수있는 동적 객체를 반환합니다.
System.Web.Helpers 어셈블리 (.NET 4.0)에 포함되어 있습니다.
var dynamicObject = Json.Decode(jsonString);
.NET 4.0에는이를위한 내장 라이브러리가 있습니다.
using System.Web.Script.Serialization;
JavaScriptSerializer jss = new JavaScriptSerializer();
var d = jss.Deserialize<dynamic>(str);
이것이 가장 간단한 방법입니다.
Dictionary<string,object>
. 내가 빠진 것이 아닌 한, 귀하의 예제는 동적 객체를 반환하지 않습니다.
we already know how to get the dictionary and casting it to a dynamic
. 사전 일 필요는 없습니다. Json에는 사전 외에도 목록이 있습니다. 또한 목록과 사전은 중첩 될 수 있습니다. 내 코드는 이러한 모든 상황을 처리 할 수 있습니다. 그러나 당신의 방법은 할 수 없습니다.
IDynamicMetaObjectProvider
(또는 예를 들어 사용 ExpandoObject
)이 가능합니다. 이를 사용 dynamic
하면 코드를 사용할 수 d.code
있습니다. 사전을 역동적으로 캐스트하는 것은 무의미합니다.
타사 DLL 파일없이 객체에 대한 간단한 "문자열 JSON 데이터":
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
참고 : 사용자 정의 개체를 사용할 수도 있습니다.
Personel item = serializer.Deserialize<Personel>(getString);
myObject["myprop"]
있습니까? 나는 그것이 런타임에 완료되었음을 알고 있지만 그것을 통해 액세스하는 것이 어떻게 myObject["myprop"]
유효합니까?
JsonFx 는 JSON 컨텐츠를 동적 오브젝트로 직렬화 해제 할 수 있습니다.
동적 유형과의 직렬화 (.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]}
Expando Objects를 사용하는 DynamicJsonConverter의 새 버전을 만들었습니다. Json.NET을 사용하여 동적을 JSON으로 다시 직렬화하려고했기 때문에 expando 객체를 사용했습니다.
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) })); }
}
}
}
Newtonsoft.Json을 사용하는 다른 방법 :
dynamic stuff = Newtonsoft.Json.JsonConvert.DeserializeObject("{ color: 'red', value: 5 }");
string color = stuff.color;
int value = stuff.value;
가장 간단한 방법은 다음과 같습니다.
다음과 같은 코드를 사용하십시오.
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.
JavaScriptSerializer를 확장하여 객체를 확장하기 위해 작성한 사전을 재귀 적으로 복사 한 다음 동적으로 사용할 수 있습니다.
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;
}
}
그런 다음 확장명을 정의한 네임 스페이스에 대해 using 문만 있으면됩니다 (System.Web.Script.Serialization에서 확장명을 정의하는 것만 고려하면됩니다. 다른 트릭은 네임 스페이스를 사용하지 않는 것입니다. 진술)) 그리고 당신은 그렇게 소비 할 수 있습니다 :
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
http://json2csharp.com/ 을 사용 하여 JSON 객체를 나타내는 클래스를 얻습니다.
입력:
{
"name":"John",
"age":31,
"city":"New York",
"Childs":[
{
"name":"Jim",
"age":11
},
{
"name":"Tim",
"age":9
}
]
}
산출:
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; }
}
그런 다음 Newtonsoft.Json 을 사용하여 클래스를 채 웁니다.
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);
}
}
}
다음과 같이 호출 할 수 있습니다.
Person jsonClass = JObjects.Get<Person>(stringJson);
string stringJson = JObjects.Get(jsonClass);
추신:
JSON 변수 이름이 유효한 C # 이름이 아닌 경우 (이름은로 시작 $
) 다음과 같이 수정할 수 있습니다.
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; }
}
내 코드에서 이와 같이 사용하고 있으며 잘 작동합니다.
using System.Web.Script.Serialization;
JavaScriptSerializer oJS = new JavaScriptSerializer();
RootObject oRootObject = new RootObject();
oRootObject = oJS.Deserialize<RootObject>(Your JSon String);
내가 CodeProject에 작성한 기사를 보아라.
여기에 모두 다시 게시하는 방법이 너무 많으며 해당 기사에 키 / 필수 소스 파일이 첨부되어 있으므로 덜 중요합니다.
또 다른 옵션은 "JSON을 클래스로 붙여 넣기"로 빠르고 쉽게 역 직렬화 할 수 있습니다.
JSON.NET에서 역 직렬화는 JObject
해당 라이브러리에 포함 된 클래스를 사용하여 동적 일 수 있습니다 . 내 JSON 문자열은 다음 클래스를 나타냅니다.
public class Foo {
public int Age {get;set;}
public Bar Bar {get;set;}
}
public class Bar {
public DateTime BDay {get;set;}
}
이제 위의 클래스를 참조하지 않고 문자열을 역 직렬화합니다.
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());
또는 더 깊이 가고 싶다면 :
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());
완전한 예는 post 를 참조하십시오 .
C #을위한 간단한 JSON 라이브러리 인 SimpleJson이 있습니다.
.NET 3.5 이상, Silverlight 및 Windows Phone 7을 지원합니다.
.NET 4.0에 대한 동적 지원
NuGet 패키지로 설치할 수도 있습니다
Install-Package SimpleJson
JavaScript와 함께 DataSet (C #)을 사용하십시오. DataSet 입력으로 JSON 스트림을 생성하기위한 간단한 함수입니다. (다중 테이블 데이터 세트)와 같은 JSON 컨텐츠를 작성하십시오.
[[{a:1,b:2,c:3},{a:3,b:5,c:6}],[{a:23,b:45,c:35},{a:58,b:59,c:45}]]
클라이언트 측에서만 eval을 사용하십시오. 예를 들어
var d = eval('[[{a:1,b:2,c:3},{a:3,b:5,c:6}],[{a:23,b:45,c:35},{a:58,b:59,c:45}]]')
그런 다음 사용하십시오.
d[0][0].a // out 1 from table 0 row 0
d[1][1].b // out 59 from table 1 row 1
// Created 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;
}
System.Web.Extensions의 참조를 추가하고이 네임 스페이스 using System.Web.Script.Serialization;
를 맨 위에 추가하십시오 .
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();
}
System.Web.Extensions의 참조를 추가하고이 네임 스페이스 using System.Web.Script.Serialization;
를 맨 위에 추가하십시오 .
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();
}
와 Cinchoo의 ETL - 동적 객체로 JSON을 구문 분석하기 위해 사용할 수있는 오픈 소스 라이브러리 :
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 address: " + rec.ip);
}
}
산출:
Action: open
Timestamp: 2018-09-05 20:46:00
URL: http://www.google.com
IP address: 66.102.6.98
면책 조항 : 나는이 도서관의 저자입니다.
이 방법으로 시도하십시오!
JSON 예 :
[{
"id": 140,
"group": 1,
"text": "xxx",
"creation_date": 123456,
"created_by": "xxx@gmail.co",
"tags": ["xxxxx"]
}, {
"id": 141,
"group": 1,
"text": "xxxx",
"creation_date": 123456,
"created_by": "xxx@gmail.com",
"tags": ["xxxxx"]
}]
C # 코드 :
var jsonString = (File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(),"delete_result.json")));
var objects = JsonConvert.DeserializeObject<dynamic>(jsonString);
foreach(var o in objects)
{
Console.WriteLine($"{o.id.ToString()}");
}