如何在没有 JSON.NET 库的情况下解析 JSON?

Posted

技术标签:

【中文标题】如何在没有 JSON.NET 库的情况下解析 JSON?【英文标题】:How to parse JSON without JSON.NET library? 【发布时间】:2012-03-23 07:21:55 【问题描述】:

我正在尝试在 Visual Studio 2011 上为 Windows 8 构建 Metro 应用程序。 虽然我正在尝试这样做,但在没有 JSON.NET 库的情况下如何解析 JSON 时遇到了一些问题(它还不支持 Metro 应用程序)。

无论如何,我想解析这个:


   "name":"Prince Charming",
   "artist":"Metallica",
   "genre":"Rock and Metal",
   "album":"Reload",
   "album_image":"http:\/\/up203.siz.co.il\/up2\/u2zzzw4mjayz.png",
   "link":"http:\/\/f2h.co.il\/7779182246886"

【问题讨论】:

您可以像我们这些人在JSON.NET 和其他库出现之前所做的那样使用字符串操作来做到这一点。 使用 javascriptSerializer。看看这个答案:***.com/questions/8405458/… 你不应该问这个,MS 并没有表现出对 Json 那样的爱。在System.Web.Helpers 中有Json,在System.ServiceModel.Web 中有JsonQueryStringConverter,在System.Web.Script.Serialization 中有JavascriptSerializer,在DataContractJsonSerializerSystem.Runtime.Serialization.Json... 一点也不混乱。 Heck MS 甚至决定在其 ASP.NET Web API 中包含第三方 Json.NET。如果您认为这还不够,MS 正在提出System.Json,但目前不适合消费。而Windows 8是MS的特例,所以Windows.Data.Json中也有JsonValue,仅适用于Windows 8及以上。 截至 2016 年底:似乎 Microsoft has embraced Json.NET 并可能放弃了从未正式发布的 System.Json:msdn.microsoft.com/en-us/library/… 谈论“预览”和 Nuget package 两者(仍然)标记为“Beta”并且已未列出,表明已弃用。 (有一个已发布的System.Json,但它仅适用于 Silverlight)。 【参考方案1】:

您可以使用在 .NET 4.5 中添加的 System.Json Namespace 中的类。您需要添加对System.Runtime.Serialization 程序集的引用

JsonValue.Parse() Method 解析 JSON 文本并返回 JsonValue:

JsonValue value = JsonValue.Parse(@" ""name"":""Prince Charming"", ...");

如果您传递带有 JSON 对象的字符串,您应该能够将值转换为 JsonObject:

using System.Json;


JsonObject result = value as JsonObject;

Console.WriteLine("Name .... 0", (string)result["name"]);
Console.WriteLine("Artist .. 0", (string)result["artist"]);
Console.WriteLine("Genre ... 0", (string)result["genre"]);
Console.WriteLine("Album ... 0", (string)result["album"]);

这些类与System.Xml.Linq Namespace 中的类非常相似。

【讨论】:

您需要添加对 System.Runtime.Serialization 程序集的引用。 使用 Nuget 安装 system.json : Install-Package System.Json 如果找不到包,请确保添加版本号。示例:PM> Install-Package System.Json -Version 4.0.20126.16343。在此处查找当前版本:nuget.org/packages/System.Json System.Json 仍处于测试阶段,因此 Nuget 包似乎是获取它的方法。它不是内置在最新的完整 Framework V 4.5.1 中。就我个人而言,我喜欢 Json.Net 的 API,它比 Windows.Data.Json 或 System.Json 更简洁、更快。见james.newtonking.com/json/help/html/… 找不到system.json【参考方案2】:

我使用它...但从未做过任何 Metro 应用程序开发,所以我不知道对您可用的库有任何限制。 (注意,你需要将你的类标记为 DataContract 和 DataMember 属性)

public static class JSONSerializer<TType> where TType : class

    /// <summary>
    /// Serializes an object to JSON
    /// </summary>
    public static string Serialize(TType instance)
    
        var serializer = new DataContractJsonSerializer(typeof(TType));
        using (var stream = new MemoryStream())
        
            serializer.WriteObject(stream, instance);
            return Encoding.Default.GetString(stream.ToArray());
        
    

    /// <summary>
    /// DeSerializes an object from JSON
    /// </summary>
    public static TType DeSerialize(string json)
    
        using (var stream = new MemoryStream(Encoding.Default.GetBytes(json)))
        
            var serializer = new DataContractJsonSerializer(typeof(TType));
            return serializer.ReadObject(stream) as TType;
        
    

所以,如果你有这样的课程......

[DataContract]
public class MusicInfo

    [DataMember]
    public string Name  get; set; 

    [DataMember]
    public string Artist  get; set; 

    [DataMember]
    public string Genre  get; set; 

    [DataMember]
    public string Album  get; set; 

    [DataMember]
    public string AlbumImage  get; set; 

    [DataMember]
    public string Link  get; set; 


那你就这样用吧……

var musicInfo = new MusicInfo

     Name = "Prince Charming",
     Artist = "Metallica",
     Genre = "Rock and Metal",
     Album = "Reload",
     AlbumImage = "http://up203.siz.co.il/up2/u2zzzw4mjayz.png",
     Link = "http://f2h.co.il/7779182246886"
;

// This will produce a JSON String
var serialized = JSONSerializer<MusicInfo>.Serialize(musicInfo);

// This will produce a copy of the instance you created earlier
var deserialized = JSONSerializer<MusicInfo>.DeSerialize(serialized);

【讨论】:

如何使用它?它一直问我要 TType,那是什么? 如果你的类型(类)被称为 MyType,你会像这样使用它: JSONSerializer.Serialize() 和 JSONSerializer.Deserialize(myInstanceOfMyType) 如果您使用的是框架的 v4.5,dtb 似乎有一种更新的原生方式(上面已回答)。 你必须使用 Encoding.UTF8.GetString(stream.ToArray());如果你想支持 unicode。 如果您的自定义对象中有一个没有 DataContract 和 DataMember 属性的对象,您将如何处理?【参考方案3】:

对于那些没有 4.5 的人,这是我的读取 json 的库函数。它需要对System.Web.Extensions 的项目引用。

using System.Web.Script.Serialization;

public object DeserializeJson<T>(string Json)

    JavaScriptSerializer JavaScriptSerializer = new JavaScriptSerializer();
    return JavaScriptSerializer.Deserialize<T>(Json);

通常情况下,json是根据合同写出来的。该合同可以而且通常会被编入一个类 (T)。有时您可以从 json 中取出一个单词并搜索对象浏览器以找到该类型。

示例用法:

给定 json

"logEntries":[],"value":"My Code","text":"My Text","enabled":true,"checkedIndices":[],"checkedItemsTextOverflows":false

您可以将其解析为 RadComboBoxClientState 对象,如下所示:

string ClientStateJson = Page.Request.Form("ReportGrid1_cboReportType_ClientState");
RadComboBoxClientState RadComboBoxClientState = DeserializeJson<RadComboBoxClientState>(ClientStateJson);
return RadComboBoxClientState.Value;

【讨论】:

【参考方案4】:

您是否尝试过使用 JavaScriptSerializer ? 还有DataContractJsonSerializer

【讨论】:

不,你能解释一下那是什么吗?谢谢老兄 DataContract: msdn.microsoft.com/en-us/library/bb908432.aspx JavaScriptSerializer: msdn.microsoft.com/en-us/library/… 回复JavaScriptSerializer:在撰写本文时,其MSDN page 建议改用Json.NET。【参考方案5】:

我需要一个没有任何第三方依赖或 nuget 的 JSON 序列化器和反序列化器,它可以支持旧系统,因此您不必在 Newtonsoft.Json、System.Text.Json、DataContractSerializer、JavaScriptSerializer 等之间进行选择,具体取决于在目标平台上。

所以我在这里启动了这个开源 (MIT) 项目:

https://github.com/smourier/ZeroDepJson

它只是一个 C# 文件 ZeroDepJson.cs,兼容 .NET Framework 4.x 到 .NET Core 和 .NET 5。

请注意,它可能不如上述所有库(尤其是在性能方面),但它应该还算不错且无摩擦。

【讨论】:

【参考方案6】:

您可以使用DataContractJsonSerializer。有关详细信息,请参阅此link。

【讨论】:

我用这段代码试过了 DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Song));歌曲项 = (Song)ser.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(song))); Debug.WriteLine(item.name); 它给了我一个错误 错误是类型'Test1.Song'不能被序列化。考虑使用 DataContractAttribute 属性对其进行标记,并使用 DataMemberAttribute 属性标记您想要序列化的所有成员。如果该类型是一个集合,请考虑使用 CollectionDataContractAttribute 对其进行标记。有关其他支持的类型,请参阅 Microsoft .NET Framework 文档。 @EliRevah - 您需要使用类的 [DataContract] 属性定义反序列化的数据协定,并为每个成员添加 [DataMember] 属性。【参考方案7】:
using System;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;

namespace OTL

    /// <summary>
    /// Before usage: Define your class, sample:
    /// [DataContract]
    ///public class MusicInfo
    ///
    ///   [DataMember(Name="music_name")]
    ///   public string Name  get; set; 
    ///   [DataMember]
    ///   public string Artistget; set;
    ///
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class OTLJSON<T> where T : class
    
        /// <summary>
        /// Serializes an object to JSON
        /// Usage: string serialized = OTLJSON&lt;MusicInfo&gt;.Serialize(musicInfo);
        /// </summary>
        /// <param name="instance"></param>
        /// <returns></returns>
        public static string Serialize(T instance)
        
            var serializer = new DataContractJsonSerializer(typeof(T));
            using (var stream = new MemoryStream())
            
                serializer.WriteObject(stream, instance);
                return Encoding.Default.GetString(stream.ToArray());
            
        

        /// <summary>
        /// DeSerializes an object from JSON
        /// Usage:  MusicInfo deserialized = OTLJSON&lt;MusicInfo&gt;.Deserialize(json);
        /// </summary>
        /// <param name="json"></param>
        /// <returns></returns>
        public static T Deserialize(string json)
        
            if (string.IsNullOrEmpty(json))
                throw new Exception("Json can't empty");
            else
                try
                
                    using (var stream = new MemoryStream(Encoding.Default.GetBytes(json)))
                    

                        var serializer = new DataContractJsonSerializer(typeof(T));
                        return serializer.ReadObject(stream) as T;
                    
                
                catch (Exception e)
                
                    throw new Exception("Json can't convert to Object because it isn't correct format.");
                
        
    

【讨论】:

【参考方案8】:

很久以前我写了一个小函数来做这个,它需要System.Runtime.Serialization.Json命名空间。

要使用你需要调用

JConvert<string,object>(str); //to Parse string to non anonymous <object>
JConvert<object,string>(obj); //to convert <obj> to string

看看这是否适合你。它适用于小数据集,但没有对大数据源进行测试。

// Json Serializer without NewtonSoft
public static class JsonHelper

    public static R JConvert<P,R>(this P t)
           
        if(typeof(P) == typeof(string))
        
            var return1 =  (R)(JsonDeserializer<R>(t as string));
            return return1;
        
        else
        
            var return2 =  (JsonSerializer<P>(t));
            R result = (R)Convert.ChangeType(return2, typeof(R));
            return result;
           
    
    
    private static String JsonSerializer<T>(T t)
    
        var stream1 = new MemoryStream();
        var ser = new DataContractJsonSerializer(typeof(T));
        ser.WriteObject(stream1, t);
        stream1.Position = 0;
        var sr = new StreamReader(stream1);     
        return (sr.ReadToEnd());
    
    
    private static T JsonDeserializer<T>(string jsonString)
    
        T deserializedUser = default(T);
        var ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
        var ser = new DataContractJsonSerializer(typeof(T));
        deserializedUser = (T)ser.ReadObject(ms);// as T;
        ms.Close();
        return deserializedUser;
    

【讨论】:

以上是关于如何在没有 JSON.NET 库的情况下解析 JSON?的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有外部库的情况下解析包含对象列表的对象列表

如何在没有外部库的情况下在 React 中实现 Google Maps JS API?

在没有 JS 库的情况下在 <canvas> 上为 spritesheet 设置动画 [重复]

如何在不使用 Python 中的外部库的情况下解析 arff 文件

如何在没有外部库的情况下在 React 中播放/暂停视频?

解析 JWT 令牌以仅在 C# 或 Blazor 中没有外部库的情况下获取有效负载内容