【问题标题】:Json.Net unexpected characters ("\") when serializing my entities序列化我的实体时 Json.Net 意外字符(“\”)
【发布时间】:2011-01-18 22:30:46
【问题描述】:

我正在使用优秀的 Json.Net 库来序列化我由实体框架生成的实体。我使用以下代码:

using (MyVoucherEntities context = new MyVoucherEntities())
{
  List<MyObject> list = context.MyObjects.ToList();
  string json = JsonConvert.SerializeObject(list);
}

一切顺利,我的意思是,对象已正确序列化,除了一个想法:它添加了转义字符“\”,这让我在客户端反序列化时做噩梦。

 [
     {
         \"$id\": \"1\",
         \"CreationDate\": \"\\\/Date(1293186324257+0000)\\\/\",
        \"ImageUrl\": \"http:\/\/www.google.com\",
         \"Title\": \"Here is a title\"
     } ]

有人知道为什么以及如何摆脱这些转义字符斜线“\”吗?

【问题讨论】:

  • @Jon Skeet 很可能是正确的,您在反序列化时遇到什么问题或错误消息?
  • 反序列化的问题不是由于转义字符 (),而是由于序列化文本以“[”开头并以“]”结尾。请参阅@Jone Polvora 的回答。如果您使用 {"dummyRoot": 和 append } 附加您的序列化文本,您会发现它可以很好地序列化。

标签: c# entity-framework wcf json.net


【解决方案1】:

我怀疑它根本没有实际上添加转义字符。我怀疑你只是在调试器中查看字符串,那是添加转义。

尝试将其转储到文件或控制台。

【讨论】:

  • 转储到表单文本框也对我有用。很好的提示谢谢
【解决方案2】:

我找到了字符串中包含转义字符的原因 ("\")。序列化我的对象后,我通过 WCF 将 JSON 字符串返回到客户端应用程序。显然,WCF 在将字符串发送到网络之前会自动将这些字符添加到字符串中。这是一种默认行为,显然是强制性的。

由于我不想要这些转义字符,解决方法是将服务的返回类型更改为 Stream 等,在内存流中返回您的 JSON 字符串。它运行完美,速度非常快。

【讨论】:

  • 呸!你特别说它是在序列化时添加它们!很高兴你把它修好了。 :) 你可以 +1 你觉得有帮助的答案,虽然我不记得你是否可以在你的代表水平上做到这一点......
  • 你得到转义字符的真正原因是因为你手动序列化你的返回值 WCF也序列化你的(已经序列化的)返回值作为它的自然行为。因此 JSON 以其中的转义字符结束。通过作为流返回,您实际上是在围绕 WCF 序列化程序进行结束运行。另一种可能的解决方案是简单地从您的方法中返回非序列化对象并让 WCF 序列化它,但这意味着不使用 Json.Net。
  • @Brian - 你是对的。我遇到了同样的问题,但这很烦人,因为我想要一个仅由控制器使用的自定义转换器(因此,我不能注释类说“总是使用这个自定义转换器序列化)。如果我使用控制器逻辑中的自定义转换器,我返回一个字符串,然后 WCF 重新序列化数据...
【解决方案3】:

这是无效的 JSON,因为序列化对象列表的结果是一个数组,即 json 将以 [ 开头并以 ] 结尾。要解决此问题,您需要将对象列表包装在根对象(类的任何实例或匿名对象)中,因此,生成的字符串将以 { 开头并以 } 结尾。

例如:

var output = new List<object>();
var json = JsonConvert.SerializeObject(new { root = output }, Formatting.Indented);
Response.Write(json);

【讨论】:

  • 优雅!用 new { x = y } 创建对象的 C# 功能是什么?我已经将它用于无构造器实例化,但不是这样。
  • 是的,它在 C# 中被称为匿名类型,当您不想为像这样的简单任务创建一个普通的“命名”类时非常有用。
  • 在内部编译器会为你生成一个类
【解决方案4】:

这个有帮助吗?我在我的 WebService 中使用它来返回 Json 内容:

private HttpContent ConvertToJsonContent(object content)
{
  string jsonObject = JsonConvert.SerializeObject(content, Newtonsoft.Json.Formatting.Indented);
  return new StringContent(jsonObject, Encoding.UTF8, "application/json");
}

如果字符串有“\”,则两个“\\”会回来。你可以通过使用 Unescape 来避免这种情况

private HttpContent ConvertToJsonContent(object content)
{
  string jsonObject = Regex.Unescape(JsonConvert.SerializeObject(content, Newtonsoft.Json.Formatting.Indented));
  return new StringContent(jsonObject, Encoding.UTF8, "application/json");
}

【讨论】:

  • 虽然其他答案对为什么字符没有被转义给出了很好的答案,但 Unescape 解决方案是处理我遇到的类似问题的快速而良好的解决方案.
【解决方案5】:

我应该注意到你没有完全引用输出的东西(我得到了在你的答案中工作的 url - 应该已经编辑到你的问题中而不是作为答案)。我在文件中得到的字符串是这样的:

"[{\"$id\":\"1\",\"CreationDate\":\"\\\/Date(1293186324257+0000)\\\/\",\"ImageUrl\":\"http:\/\/www.c-tina.com\/MyVoucherAdmin\/Images\/shop22\/burger.jpg\",\"Title\":\"Get one burger for free\",\"Description\":\"Bla lbzlfpzkfgmzke\\rdmjdgmj\\r\\r\\rlgfpzkegmkzepk\",\"ShopId\":22,\"PromotionId\":15,\"Shop\":null,\"Features\":[],\"SingleStats\":[],\"WhatsHots\":[],\"EntityKey\":{\"$id\":\"2\",\"EntitySetName\":\"Promotions\",\"EntityContainerName\":\"MyVoucherEntities\",\"EntityKeyValues\":[{\"Key\":\"PromotionId\",\"Type\":\"System.Int32\",\"Value\":\"15\"}]}}]"

对我来说,关键是前面和结尾处都有未转义的引号,这让我认为无论输出什么,它都决定它需要被引用,如果你用引号括起来,你必须逃避那些在里面。

如果没有看到完整的输出,很难说问题是在您上面引用的用于生成 JSON 的代码中,还是在处理此问题的后续步骤中存在导致引用的问题。您是否已调试并确认您的序列化调用的输出肯定会产生转义版本,而不是可能在稍后阶段完成?如果您不习惯调试器,请注意 Jon Skeet 的建议,将其转储到文件或控制台以确保不会造成混淆。

【讨论】:

  • 克里斯,谢谢您的回答。我使用调试器进行了验证,确实是在序列化时添加引号,而不是在后面的步骤中。尽管如此,我在另一个项目中尝试了相同的代码,但由于我不知道的原因,它没有添加引号......它可能是我正在序列化的对象的类型,它通过 Json 生成这些引号。网络图书馆?
  • 我自己并没有真正使用过 Json.net 库,所以我不确定是否可以提供更多建议。您可以尝试在这些对象中使​​用不同的对象和不同的数据,看看它是否有所作为。我对它为什么会这样做感到有点困惑,但我想不出任何你想要的情况。出于兴趣,如果您通过反序列化方法直接运行它,它是否按预期工作?无所事事地想知道这里是否可能存在某种错误..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-27
  • 1970-01-01
  • 1970-01-01
  • 2016-05-14
  • 1970-01-01
  • 2018-02-04
相关资源
最近更新 更多