15

我有这样的json

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

我有两个这样的对象

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 字符串。你能帮助我吗 ?

4

6 回答 6

26

您不需要编写任何转换器,只需使用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 序列化为隐藏属性,然后在访问器调用中进行字符串转换。

于 2015-12-08T07:14:51.767 回答
7

您必须编写一个自定义转换器类(派生自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 对象,但将对象的序列化版本作为字符串返回。有一点开销,因为对象被反序列化为 aJObject然后再次序列化,但对我来说这是最简单的方法。也许你有更好的主意。

于 2012-06-27T09:57:00.283 回答
2

我使用自定义 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;
        }
    }
}
于 2014-12-05T08:13:16.313 回答
2

如果您担心开销因为对象被反序列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#

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

于 2012-12-03T05:10:42.983 回答
1

正如chakrit 所建议的那样,您可以做这样的事情来为您的对象提供一个字符串签名,同时使用 JRaw 来完成真正的工作。

    [JsonProperty("Data")]
    public JRaw Raw { get; set; }

    [JsonIgnore]
    public string Data
    {
        get => Raw?.Value as string;
        set => Raw = new JRaw(value);
    }
于 2018-03-01T16:31:02.243 回答
0

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

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

于 2014-01-14T10:10:20.850 回答