问题描述
我正在尝试使用声称返回 JSON,但实际上总是返回 JSONP 的 Web 服务.我看不到改变该服务行为的方法.
I am trying to consume a web service that claims to return JSON, but actually always returns JSONP. I don't see a way to change that service's behavior.
我想使用 NewtonSoft Json.Net 来解析结果.我已经声明了一个类,我们称它为 MyType,我想将内部 JSON 结果反序列化为.
I would like to use NewtonSoft Json.Net to parse the result. I have declared a class, let's call it MyType that I want to deserialize the inner JSON result into.
JSONP:
parseResponse({
"total" : "13,769",
"lower" : "1",
"upper" : "20"})
如您所见,这不是正确的 JSON,因为它具有 parseResponse(
前缀和 )
后缀.虽然此示例非常简单,但实际响应可能会很长,大约 100Ks.
As you can see this is not correct JSON as it has parseResponse(
prefix and )
suffix. While this example is very simple, the actual response can be quite long, on the order of 100Ks.
我的类型:
public class MyType
{
public Decimal total;
public int lower;
public int upper;
}
在我将 Web 服务响应放入流和 JsonTextReader 后,我尝试像这样反序列化:
After I get my web service response into a stream and JsonTextReader I try to deserialize like this:
(MyType)serializer.Deserialize(jsonTextReader, typeof(MyType));
当然,我的结果是 null,因为 parseResponse 带有圆括号.
Of course I get null for a result because there is that pesky parseResponse with round brackets.
我看过 这个问题不幸的是,这无济于事.我实际上是使用 JsonTextReader
来输入 JSON,而不是字符串(并且更喜欢这样以避免创建巨大字符串的性能影响).即使我使用该问题的建议,它看起来也很危险,因为它使用了全局替换.如果没有使用流的好方法,那么安全解析字符串的答案就可以了.
I've taken a look at this question which unfortunately does not help. I'm actually using a JsonTextReader
to feed in the JSON, rather than a string (and prefer so to avoid the performance hit of creating huge a string). Even if I'd use the suggestion from that question, it looks dangerous as it uses a global replace. If there is no good way to use a stream, an answer with safe parsing of strings would be okay.
推荐答案
如果我将您的问题解释如下:
If I interpret your question as follows:
我正在尝试从 Stream
中反序列化一些 JSON.JSON"实际上是 JSONP 格式,因此包含一些我想忽略的前缀和后缀文本.如何跳过前缀和后缀文本,同时仍然直接从流中读取和反序列化,而不是将整个流加载到字符串中?
I am trying to deserialize some JSON from a
Stream
. The "JSON" is actually in JSONP format and so contains some prefix and postfix text I would like to ignore. How can I skip the prefix and postfix text while still reading and deserializing directly from stream rather than loading the entire stream into a string?
然后您可以使用以下扩展方法从 JSONP 流中反序列化您的 JSON:
Then you can deserialize your JSON from a JSONP stream using the following extension method:
public static class JsonExtensions
{
public static T DeserializeEmbeddedJsonP<T>(Stream stream)
{
using (var textReader = new StreamReader(stream))
return DeserializeEmbeddedJsonP<T>(textReader);
}
public static T DeserializeEmbeddedJsonP<T>(TextReader textReader)
{
using (var jsonReader = new JsonTextReader(textReader.SkipPast('(')))
{
var settings = new JsonSerializerSettings
{
CheckAdditionalContent = false,
};
return JsonSerializer.CreateDefault(settings).Deserialize<T>(jsonReader);
}
}
}
public static class TextReaderExtensions
{
public static TTextReader SkipPast<TTextReader>(this TTextReader reader, char ch) where TTextReader : TextReader
{
while (true)
{
var c = reader.Read();
if (c == -1 || c == ch)
return reader;
}
}
}
注意事项:
在构造
JsonTextReader
之前,我构造了一个StreamReader
并跳过流中的第一个'('
字符.这个将StreamReader
定位在实际 JSON 的开头.
Prior to constructing the
JsonTextReader
I construct aStreamReader
and skip past the first'('
character in the stream. This positions theStreamReader
at the beginning of the actual JSON.
在反序列化之前,我设置了 JsonSerializerSettings.CheckAdditionalContent = false
告诉序列化程序忽略 JSON 内容结束后的任何字符.奇怪的是,尽管默认值似乎已经是 false
,但有必要明确地执行此操作,因为 基础字段可以为空.
Before deserialization I set JsonSerializerSettings.CheckAdditionalContent = false
to tell the serializer to ignore any characters after the end of the JSON content. Oddly enough it is necessary to do this explicitly despite the fact that the default value seems to be false
already, since the underlying field is nullable.
通过将 StringReader
传递给 DeserializeEmbeddedJsonP
string
反序列化嵌入的 JSONP;代码>.这样做可以避免通过修剪前缀和后缀文本来创建新字符串,因此即使是较小的字符串也可以提高性能和内存使用.
The same code can be used to deserialize embedded JSONP from a string
by passing a StringReader
to DeserializeEmbeddedJsonP<T>(TextReader reader);
. Doing so avoids the need to create a new string by trimming the prefix and postfix text and so may improve performance and memory use even for smaller strings.
示例工作 .Net fiddle.
这篇关于如何反序列化 JSONP 响应(最好使用 JsonTextReader 而不是字符串)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!