【问题标题】:Get Raw json string in Newtonsoft.Json Library在 Newtonsoft.Json 库中获取原始 json 字符串
【发布时间】:2012-06-01 05:10:03
【问题描述】:

我有这样的json

{
    "name": "somenameofevent",
    "type": "event",
    "data": {
        "object": {
            "age": "18",
            "petName": "18"
        },
        "desct": {
        }
    }
}

我有 2 个这样的对象

public class CustEvent
{
    [JsonProperty("name")]
    public string Name { get; set; }
    [JsonProperty("type")]
    public string EventType{ get; set; }
    [JsonProperty("data")]
    public SomeData Data{ get; set; }
}

public class SomeData
{
    [JsonProperty("object")]
    public String SomeObject { get; set;}
    [JsonProperty("dsct")]
    public String SomeDesct { get; set; }
}

我使用将 json 解析为对象 Newtonsoft.NET 库。以及如何将 RAW JSON 转换为 SomeObject 、 SomeDesct 属性?在 JSON 中,“data.object ...”是复杂对象,我只想获取这些属性的原始 JSON 字符串。你能帮帮我吗?

【问题讨论】:

    标签: .net json json.net


    【解决方案1】:

    你不需要编写任何转换器,只需使用JRaw类型如下:

    public class SomeData
    {
        [JsonProperty("object")]
        public JRaw SomeObject { get; set;}
        [JsonProperty("dsct")]
        public JRaw SomeDesct { get; set; }
    }
    

    然后您可以通过检查.Value 属性来访问原始值:

    var rawJsonDesct = (string)data.SomeDesct.Value;
    

    如果您想保留string 签名,只需将 JSON 序列化为隐藏属性,然后在访问器调用中进行字符串转换。

    【讨论】:

    • 绝对是最简单的解决方案。
    • 这不保持缩进,有什么解决办法吗?
    • 重要提示:JRaw 不保留原始数据。它规范化字符串,删除空格并截断长小数(丢失潜在的重要数据)。
    • 不知道为什么没有多提这个选项。这似乎是最好的解决方案,因为当您不想解析对象的一部分时(通常是您想要保留为字符串以供以后使用的有效负载)。
    【解决方案2】:

    您必须编写一个自定义转换器类(派生自 Newtonsoft.Json.JsonConverter),它指示反序列化器读取整个对象并返回该对象的 JSON 字符串。

    然后你必须用JsonConverter 属性来装饰属性。

    [JsonConverter(typeof(YourCustomConverterClass))]
    public string SomeObject { get; set; }
    

    网络上有关于如何创建自定义转换器的很好的教程,但是 - 为了您的方便 - 您的转换器的核心可能如下所示:

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        return JObject.Load(reader).ToString();
    }
    

    此方法读取完整的 JSON 对象,但将对象的序列化版本作为字符串返回。有一点开销,因为对象被反序列化为JObject,然后再次序列化,但对我来说这是最简单的方法。也许你有更好的主意。

    【讨论】:

      【解决方案3】:

      如果您担心开销因为对象被反序列化为 JObject a 然后再次序列化(@fero 提供的解决方案),那么您可以尝试以下操作。

      方法 1:创建您自己的自定义 JsonConverter 并覆盖 ReadJson

      using(var jsonReader = new JsonTextReader(myTextReader))
      {
        while(jsonReader.Read()){
          if(jsonReader.TokenType.PropertyName=="SomeDesct")
          {
            //do what you want
          } 
        }
      }
      

      更多详情请查看链接Incremental JSON Parsing in C#

      方法二:读取json字符串并应用字符串函数或正则表达式函数得到所需的字符串。

      【讨论】:

        【解决方案4】:

        我使用自定义 JsonConverter 的这个实现。

        public class RawJsonConverter: JsonConverter
        {
            public override bool CanConvert(Type objectType)
            {
                return objectType == typeof(string);
            }
        
            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                var sb = new StringBuilder();
                JsonToken previousToken = JsonToken.None;
        
                if (reader.TokenType == JsonToken.StartObject)
                {
                    sb.Append('{');
                    int depth = 1;
                    while (depth > 0)
                    {
                        if (!reader.Read())
                            break;
                        switch (reader.TokenType)
                        {
                            case JsonToken.PropertyName:
                                if (previousToken == JsonToken.Boolean || previousToken == JsonToken.Integer || previousToken == JsonToken.Float)
                                    sb.Append(',');
                                sb.AppendFormat("\"{0}\":", reader.Value);
                                break;
                            case JsonToken.StartArray:
                                if (previousToken == JsonToken.EndArray)
                                    sb.Append(',');
                                sb.Append('[');
                                break;
                            case JsonToken.Boolean:
                            case JsonToken.Integer:
                            case JsonToken.Float:
                                if (previousToken == JsonToken.Boolean || previousToken == JsonToken.Integer || previousToken == JsonToken.Float)
                                    sb.Append(',');
                                sb.AppendFormat(System.Globalization.CultureInfo.InvariantCulture, "{0}", reader.Value);
                                break;
                            case JsonToken.EndArray:
                                sb.Append(']');
                                break;
                            case JsonToken.StartObject:
                                sb.Append('{');
                                depth++;
                                break;
                            case JsonToken.EndObject:
                                sb.Append('}');
                                depth--;
                                break;
                        }
                        previousToken = reader.TokenType;
                    }
                }
                return sb.ToString();
            }
        
            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {
                writer.WriteRawValue(value.ToString());
            }
        
            public override bool CanWrite
            {
                get
                {
                    return true;
                }
            }
        }
        

        【讨论】:

          【解决方案5】:

          作为chakrit suggested,您可以执行类似的操作来为您的对象提供字符串签名,同时使用JRaw 来完成实际工作。

              [JsonProperty("Data")]
              public JRaw Raw { get; set; }
          
              [JsonIgnore]
              public string Data
              {
                  get => Raw?.Value as string;
                  set => Raw = new JRaw(value);
              }
          

          【讨论】:

          • 或者相反的[JsonIgnore] public string Data; [JsonProperty("Data")] public JRaw DataRaw => new JRaw(Data); 工作得很好,在以其他方式使用数据时不需要类型转换。
          【解决方案6】:

          在您的情况下,您可以直接使用 JsonConvert 类中的静态方法

          PopulateObject(字符串值,对象目标,JsonSerializerSettings设置);

          【讨论】:

            猜你喜欢
            • 2018-04-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-06-11
            相关资源
            最近更新 更多