【问题标题】:How to parse JSON without JSON.NET library?如何在没有 JSON.NET 库的情况下解析 JSON?
【发布时间】: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。看看这个答案:stackoverflow.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.Jsonmsdn.microsoft.com/en-us/library/… 谈论“预览”和 Nuget package 两者(仍然)标记为“Beta”并且已未列出,表明已弃用。 (有一个已发布的System.Json,但它仅适用于 Silverlight)。

标签: c# json windows-8


【解决方案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

    【讨论】:

    【解决方案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 Artist{get; 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;
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2019-11-16
          • 1970-01-01
          • 1970-01-01
          • 2013-10-22
          • 2018-06-02
          • 2016-08-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多