Có cách nào để giải tuần tự hóa nội dung JSON thành kiểu động C # 4 không? Sẽ tốt hơn nếu bỏ qua việc tạo ra một loạt các lớp để sử dụng DataContractJsonSerializer
.
Có cách nào để giải tuần tự hóa nội dung JSON thành kiểu động C # 4 không? Sẽ tốt hơn nếu bỏ qua việc tạo ra một loạt các lớp để sử dụng DataContractJsonSerializer
.
Câu trả lời:
Nếu bạn hài lòng khi có sự phụ thuộc vào System.Web.Helpers
hội đồng, thì bạn có thể sử dụng Json
lớp:
dynamic data = Json.Decode(json);
Nó được bao gồm trong khung MVC như là một bản tải xuống bổ sung cho khung .NET 4. Hãy chắc chắn cung cấp cho Vlad một upvote nếu điều đó hữu ích! Tuy nhiên nếu bạn không thể giả sử môi trường máy khách bao gồm DLL này, thì hãy đọc tiếp.
Một cách tiếp cận khử lưu huỳnh thay thế được đề xuất ở đây . Tôi đã sửa đổi mã một chút để sửa lỗi và phù hợp với phong cách mã hóa của tôi. Tất cả bạn cần là mã này và một tài liệu tham khảo System.Web.Extensions
từ dự án của bạn:
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
}
Bạn có thể sử dụng nó như thế này:
string json = ...;
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
dynamic obj = serializer.Deserialize(json, typeof(object));
Vì vậy, đã cho một chuỗi JSON:
{
"Items":[
{ "Name":"Apple", "Price":12.3 },
{ "Name":"Grape", "Price":3.21 }
],
"Date":"21/11/2010"
}
Đoạn mã sau sẽ hoạt động trong thời gian chạy:
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
(là một từ khóa trong C #). Ngoài ra, TryGetMember
bạn có thể ghi đè TryGetIndex
, cung cấp cho bạn chính xác hành vi tương tự như trong JS. Sau đó, bạn có thể làm obj["params"]
hoặc obj["background-color"]
cho tên trường vụng về.
Nó khá đơn giản khi sử dụng Json.NET :
dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");
string name = stuff.Name;
string address = stuff.Address.City;
Ngoài ra 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;
Tài liệu: Truy vấn JSON bằng động
stuff
hãy làm điều gì đó như:foreach (Newtonsoft.Json.Linq.JProperty jproperty in stuff) { Console.WriteLine("jproperty.Name = {0}", jproperty.Name);}
async
phương thức. Nếu tôi làm cho phương thức đồng bộ, nó hoạt động như mong đợi. Tuy nhiên, thực hiện phương pháp async
và tôi không thể có được dynamic
, tôi chỉ nhận được một object
. Đúc rõ ràng không làm gì, vẫn chỉ cho tôi một object
. Có ai khác trải qua điều này?
Bạn có thể thực hiện việc này bằng System.Web.Helpers.Json - phương thức Giải mã của nó trả về một đối tượng động mà bạn có thể duyệt qua tùy thích.
Nó được bao gồm trong hội đồng System.Web.Helpers (.NET 4.0).
var dynamicObject = Json.Decode(jsonString);
.NET 4.0 có một thư viện tích hợp để thực hiện việc này:
using System.Web.Script.Serialization;
JavaScriptSerializer jss = new JavaScriptSerializer();
var d = jss.Deserialize<dynamic>(str);
Đây là cách đơn giản nhất.
Dictionary<string,object>
. Trừ khi tôi thiếu một cái gì đó, ví dụ của bạn không trả về một đối tượng động.
we already know how to get the dictionary and casting it to a dynamic
. Nó không phải là một từ điển. Json cũng có danh sách bên cạnh từ điển. Và cũng có thể liệt kê danh sách và từ điển. Mã của tôi có thể xử lý tất cả các tình huống này. NHƯNG phương pháp của bạn KHÔNG THỂ.
IDynamicMetaObjectProvider
(hoặc sử dụng ví dụ ExpandoObject
) có khả năng chặn các thuộc tính và tra cứu chúng trong một từ điển nội bộ. Điều này kết hợp với việc sử dụng dynamic
mã cho phép như d.code
được sử dụng. Thật vô nghĩa khi bỏ từ điển thành động.
"Chuỗi dữ liệu JSON" đơn giản để phản đối mà không cần bất kỳ tệp DLL của bên thứ ba nào:
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
Lưu ý: Bạn cũng có thể sử dụng đối tượng tùy chỉnh của mình.
Personel item = serializer.Deserialize<Personel>(getString);
myObject["myprop"]
? Tôi biết nó được thực hiện trong thời gian chạy nhưng làm thế nào để truy cập nó myObject["myprop"]
là hợp lệ?
JsonFx có thể giải tuần tự hóa nội dung JSON thành các đối tượng động.
Nối tiếp đến / từ các loại động (mặc định cho .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]}
Tôi đã tạo một phiên bản mới của DynamicJsonConverter sử dụng Đối tượng Expando. Tôi đã sử dụng các đối tượng mở rộng, vì tôi muốn tuần tự hóa lại động vào JSON bằng Json.NET.
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) })); }
}
}
}
Một cách khác sử dụng Newtonsoft.Json :
dynamic stuff = Newtonsoft.Json.JsonConvert.DeserializeObject("{ color: 'red', value: 5 }");
string color = stuff.color;
int value = stuff.value;
Cách đơn giản nhất là:
Chỉ cần bao gồm tập tin DLL này .
Sử dụng mã như thế này:
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.
Bạn có thể mở rộng JavaScriptSerializer để sao chép đệ quy từ điển mà nó đã tạo để mở rộng (các) đối tượng và sau đó sử dụng chúng một cách linh hoạt:
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;
}
}
Sau đó, bạn chỉ cần có một câu lệnh sử dụng cho không gian tên mà bạn đã xác định tiện ích mở rộng (xem xét chỉ xác định chúng trong System.Web.Script.Serialization ... một mẹo khác là không sử dụng một không gian tên, sau đó bạn không cần sử dụng tuyên bố ở tất cả) và bạn có thể tiêu thụ chúng như vậy:
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
Bạn có thể dùng using Newtonsoft.Json
var jRoot =
JsonConvert.DeserializeObject<dynamic>(Encoding.UTF8.GetString(resolvedEvent.Event.Data));
resolvedEvent.Event.Data
là phản hồi của tôi nhận được từ việc gọi sự kiện cốt lõi.
Tôi sử dụng http://json2csharp.com/ để lấy một lớp đại diện cho đối tượng JSON.
Đầu vào:
{
"name":"John",
"age":31,
"city":"New York",
"Childs":[
{
"name":"Jim",
"age":11
},
{
"name":"Tim",
"age":9
}
]
}
Đầu ra:
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; }
}
Sau đó tôi sử dụng Newtonsoft.Json để điền vào lớp:
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);
}
}
}
Bạn có thể gọi nó như thế này:
Person jsonClass = JObjects.Get<Person>(stringJson);
string stringJson = JObjects.Get(jsonClass);
Tái bút
Nếu tên biến JSON của bạn không phải là tên C # hợp lệ (tên bắt đầu bằng $
), bạn có thể sửa như thế này:
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; }
}
Vì vậy, tôi sẽ sử dụng JSON.NET để thực hiện phân tích cú pháp mức độ thấp của luồng JSON và sau đó xây dựng hệ thống phân cấp đối tượng ra khỏi các phiên bản của ExpandoObject
lớp.
Tôi đang sử dụng như thế này trong mã của tôi và nó hoạt động tốt
using System.Web.Script.Serialization;
JavaScriptSerializer oJS = new JavaScriptSerializer();
RootObject oRootObject = new RootObject();
oRootObject = oJS.Deserialize<RootObject>(Your JSon String);
Nhìn vào bài báo tôi đã viết trên CodeProject, một bài trả lời chính xác câu hỏi:
Có quá nhiều cách để đăng lại tất cả ở đây, và thậm chí ít điểm hơn vì bài viết đó có tệp đính kèm với tệp nguồn / khóa bắt buộc.
Một tùy chọn khác là "Dán JSON dưới dạng các lớp" để có thể giải nén nhanh chóng và dễ dàng.
Dưới đây là một lời giải thích tốt hơn n piccas ... 'Dán JSON như các lớp' trong ASP.NET và các công cụ web 2012.2 RC
Việc khử lưu huỳnh trong JSON.NET có thể là động khi sử dụng JObject
lớp, được bao gồm trong thư viện đó. Chuỗi JSON của tôi đại diện cho các lớp này:
public class Foo {
public int Age {get;set;}
public Bar Bar {get;set;}
}
public class Bar {
public DateTime BDay {get;set;}
}
Bây giờ chúng tôi giải tuần tự hóa chuỗi mà KHÔNG tham chiếu các lớp trên:
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());
Hoặc nếu bạn muốn đi sâu hơn:
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());
Xem bài cho một ví dụ đầy đủ.
Đối tượng bạn muốn DynamicJSONObject được bao gồm trong System.Web.Helpers.dll từ gói Trang web ASP.NET, một phần của WebMatrix.
Có một thư viện JSON nhẹ cho C # được gọi là SimpleJson .
Nó hỗ trợ .NET 3.5+, Silverlight và Windows Phone 7.
Nó hỗ trợ động cho .NET 4.0
Nó cũng có thể được cài đặt dưới dạng gói NuGet
Install-Package SimpleJson
Sử dụng tập dữ liệu (C #) với JavaScript. Một hàm đơn giản để tạo luồng JSON với đầu vào Dataset. Tạo nội dung JSON như (tập dữ liệu đa bảng):
[[{a:1,b:2,c:3},{a:3,b:5,c:6}],[{a:23,b:45,c:35},{a:58,b:59,c:45}]]
Chỉ cần phía khách hàng, sử dụng eval. Ví dụ,
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}]]')
Sau đó sử dụng:
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;
}
Để có được ExpandoObject:
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
Container container = JsonConvert.Deserialize<Container>(jsonAsString, new ExpandoObjectConverter());
Vui lòng thêm tham chiếu của System.Web.Extensions và thêm không gian tên này using System.Web.Script.Serialization;
ở đầu:
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();
}
Vui lòng thêm tham chiếu của System.Web.Extensions và thêm không gian tên này using System.Web.Script.Serialization;
ở đầu:
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();
}
Với Cinchoo ETL - một thư viện mã nguồn mở có sẵn để phân tích JSON thành một đối tượng động:
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);
}
}
Đầu ra:
Action: open
Timestamp: 2018-09-05 20:46:00
URL: http://www.google.com
IP address: 66.102.6.98
Tuyên bố miễn trừ trách nhiệm: Tôi là tác giả của thư viện này.
Hãy thử cách này!
Ví dụ 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"]
}]
Mã 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()}");
}