C# 在JsonConverter.ReadJson()中高效地获取完整的json字符串

C# 在JsonConverter.ReadJson()中高效地获取完整的json字符串,c#,json.net,C#,Json.net,如何在JsonConverter.ReadJson()中高效地获取完整的json字符串 我可以做到: public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var json = JObject.Load(reader).ToString(Formatting.None); 然而,这似乎非常低效,因为我

如何在
JsonConverter.ReadJson()
中高效地获取完整的json字符串

我可以做到:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
      var json = JObject.Load(reader).ToString(Formatting.None);
然而,这似乎非常低效,因为我无缘无故地序列化和反序列化

有更好的方法吗?

必须完全解析正在读取的JSON,以便确认JSON格式正确,并且退出时将
JsonReader
正确定位在当前值的末尾。但是,不必将整个JSON加载到中间的
JObject
层次结构中,只需将其重新转换为JSON字符串即可。相反,您可以通过以下方式获得更好的性能:

从中可以看出,此方法直接从传入的
JsonReader
流到
StringWriter
——无需加载到中间
JToken
层次结构并重新序列化——使用:

生成的
JRaw
只是将该字符串封装在其内部。(当然,不能保证生成的JSON表示一个对象,只能保证它表示格式良好的JSON。)

请注意,
JsonTextReader
将自动识别和解析中的日期和时间为
DateTime
对象,还将浮点值解析为
double
。如果您需要“最文字化”的JSON字符串,您可能希望抑制
DateTime
识别和/或将浮点值解析为
decimal
。以下扩展方法以JRaw.Create()为模型执行此任务:

public static string ReadOuterJson(this JsonReader reader, Formatting formatting = Formatting.None, DateParseHandling? dateParseHandling = null, FloatParseHandling? floatParseHandling = null)
{
    // If you would prefer a null JSON value to return an empty string, remove this line:
    if (reader.TokenType == JsonToken.Null)
        return null;
    var oldDateParseHandling = reader.DateParseHandling;
    var oldFloatParseHandling = reader.FloatParseHandling;
    try
    {
        if (dateParseHandling != null)
            reader.DateParseHandling = dateParseHandling.Value;
        if (floatParseHandling != null)
            reader.FloatParseHandling = floatParseHandling.Value;
        using (var sw = new StringWriter(CultureInfo.InvariantCulture))
        using (var jsonWriter = new JsonTextWriter(sw) { Formatting = formatting })
        {
            jsonWriter.WriteToken(reader);
            return sw.ToString();
        }
    }
    finally
    {
        reader.DateParseHandling = oldDateParseHandling;
        reader.FloatParseHandling = oldFloatParseHandling;
    }
}
然后像这样称呼它,例如:

var json = reader.ReadOuterJson(dateParseHandling: DateParseHandling.None);
有关为什么需要这样做的详细信息,请参阅:


如果您只关心JSON本身,为什么不删除JsonReader并直接使用TextReader?因为我需要它作为JsonConverter的一部分用作属性。基本上,我希望使用类型的反射到具有ToJson和FromJson方法的接口,以便我的一些对象可以定义它们以自定义方式序列化/反序列化。在上面的代码中,您根本没有使用转换器。true。我有一个接口:
interface JsonMethods{string to json();T FromJson(string s);}
如果我的类继承了这个接口,并且有我的自定义JsonConverter可以调用这些方法hanks!我用它来编写一个手动json转换器-
public static string ReadOuterJson(this JsonReader reader, Formatting formatting = Formatting.None, DateParseHandling? dateParseHandling = null, FloatParseHandling? floatParseHandling = null)
{
    // If you would prefer a null JSON value to return an empty string, remove this line:
    if (reader.TokenType == JsonToken.Null)
        return null;
    var oldDateParseHandling = reader.DateParseHandling;
    var oldFloatParseHandling = reader.FloatParseHandling;
    try
    {
        if (dateParseHandling != null)
            reader.DateParseHandling = dateParseHandling.Value;
        if (floatParseHandling != null)
            reader.FloatParseHandling = floatParseHandling.Value;
        using (var sw = new StringWriter(CultureInfo.InvariantCulture))
        using (var jsonWriter = new JsonTextWriter(sw) { Formatting = formatting })
        {
            jsonWriter.WriteToken(reader);
            return sw.ToString();
        }
    }
    finally
    {
        reader.DateParseHandling = oldDateParseHandling;
        reader.FloatParseHandling = oldFloatParseHandling;
    }
}
var json = reader.ReadOuterJson(dateParseHandling: DateParseHandling.None);