如何在 JSON 对象中转换转义的 JSON 字符串?
Posted
技术标签:
【中文标题】如何在 JSON 对象中转换转义的 JSON 字符串?【英文标题】:How do I convert an escaped JSON string within a JSON object? 【发布时间】:2017-01-02 09:40:27 【问题描述】:我从一个公共 API 接收一个 JSON 对象,该对象的属性本身就是一个转义的 JSON 字符串。
"responses":[
"info":"keep \"this\" in a string",
"body":"\"error\":\"message\":\"Invalid command\",\"type\":\"Exception\",\"code\":123"
,
"info":"more \"data\" to keep in a string",
"body":"\"error\":\"message\":\"Other error\",\"type\":\"Exception\",\"code\":321"
]
如何将此属性转换为实际的 JSON 对象(未转义),以便使用 NewtonSoft Json.NET 反序列化整个响应?
【问题讨论】:
是否要将正文转换为 JSON?它已经在 JSON 中 我尝试过使用 Newtonsoft Json.NET 进行反序列化,但在尝试将主体转换为类时出现错误。"Error converting value [JSON String] to type '[MyClass]'. Path 'responses[0].body', line 1, position 641."
查看我的编辑。我修好了
【参考方案1】:
您的 JSON 包含实际嵌入的双序列化 JSON 的 "body"
对象的文字字符串。要将其反序列化为 POCO 层次结构,而不需要在任何类型中引入中间 string Json
代理属性,您有以下几种选择:
您可以使用 LINQ to JSON 预处理您的 JSON,并将文字 "body"
字符串替换为其解析后的等价物:
var rootToken = JToken.Parse(json);
foreach (var token in rootToken.SelectTokens("responses[*].body").ToList().Where(t => t.Type == JTokenType.String))
token.Replace(JToken.Parse((string)token));
var root = rootToken.ToObject<RootObject>();
您可以为与每个 Body
对象对应的 POCO 引入通用 JsonConverter
,该对象将传入的嵌入 JSON 字符串文字解析为 LINQ to JSON
层次结构,然后对其进行反序列化:
public class EmbeddedLiteralConverter<T> : JsonConverter
public override bool CanConvert(Type objectType)
return typeof(T).IsAssignableFrom(objectType);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
if (reader.TokenType == JsonToken.Null)
return null;
var contract = serializer.ContractResolver.ResolveContract(objectType);
if (contract is JsonPrimitiveContract)
throw new JsonSerializationException("Invalid type: " + objectType);
if (existingValue == null)
existingValue = contract.DefaultCreator();
if (reader.TokenType == JsonToken.String)
var json = (string)JToken.Load(reader);
using (var subReader = new JsonTextReader(new StringReader(json)))
// By populating a pre-allocated instance we avoid an infinite recursion in EmbeddedLiteralConverter<T>.ReadJson()
// Re-use the existing serializer to preserve settings.
serializer.Populate(subReader, existingValue);
else
serializer.Populate(reader, existingValue);
return existingValue;
public override bool CanWrite get return false;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
throw new NotImplementedException();
然后像这样使用它:
var root = JsonConvert.DeserializeObject<RootObject>(json, new EmbeddedLiteralConverter<Body>());
请注意,转换器会检查传入的 JSON 令牌是否为字符串,如果不是,则直接反序列化。因此,当"body"
JSON 被双序列化和没有被双序列化时,转换器应该是可用的。
出于测试目的,我使用http://json2csharp.com/ 生成了以下目标类:
public class Error
public string message get; set;
public string type get; set;
public int code get; set;
public class Body
public Error error get; set;
public class Respons
public string info get; set;
public Body body get; set;
public class RootObject
public List<Respons> responses get; set;
【讨论】:
【参考方案2】:要将编码为 json 字符串的 json 转换为 Jobject,您始终可以使用以下技术,
var token = JToken.Parse(text);
var json = JObject.Parse((string) token);
【讨论】:
【参考方案3】:-
您可以将其反序列化为具有属性的中间类:
string Body get; set;
将“body”字符串反序列化为合适的类型
创建代表目标模型的类的新实例。
序列化该模型
这是一个使用动态类型和匿名对象的程序。
static void Main(string[] args)
var json = File.ReadAllText("JsonFile1.json");
dynamic obj = JsonConvert.DeserializeObject(json);
var dest = new
responses = ((IEnumerable<dynamic>)obj.responses).Select(x => new
info = x.info,
body = JsonConvert.DeserializeObject((string)x.body)
)
;
var destJson = JsonConvert.SerializeObject(dest);
File.WriteAllText("JsonFile2.json", destJson);
或者,如果您不想重新序列化 josn.xml,则可以构建目标类型的新版本,而不是匿名类型。
【讨论】:
@downvoter 我的回答不正确吗?像 OP 这样已经可以使用 JSON.Net 的人是否无法使用我的答案? 看起来我们都被否决了。我希望我能找到一种方法来清理 JSON,而无需为所有不同的 API 响应创建重复的类(这是一个更复杂的简化示例),我可以使用通用的东西来解析值。【参考方案4】:这是我根据Sam I am's answer 使用的可行解决方案:
dynamic obj = JsonConvert.DeserializeObject(json);
foreach (var response in (IEnumerable<dynamic>)obj.responses)
response.body = JsonConvert.DeserializeObject((string)response.body);
string result = JsonConvert.SerializeObject(obj);
【讨论】:
以上是关于如何在 JSON 对象中转换转义的 JSON 字符串?的主要内容,如果未能解决你的问题,请参考以下文章
JQuery .ajax 返回json格式,浏览器显示带有转义字符问题