【问题标题】:JSON convert JsonResult to javascript string without encoding quotationsJSON将JsonResult转换为javascript字符串而不编码引号
【发布时间】:2016-09-12 08:42:07
【问题描述】:

我需要使用ASP.NET CoreMicrosoft.AspNet.Mvc.Controller.JsonResult 转换为字符串

这是我在 ASP.NET MVC 中的代码

public async Task<string> GetJsonData()
{
    //...
    var result = GetMyComplexObject();

    //using Newtonsoft.Json.JsonConvert method
    var jsonString = JsonConvert.SerializeObject(Json(result));
    return jsonString;
}

public async Task<IActionResult> Index()
{
    var myViewModel= new MyViewModel();
    myViewModel.JsonString = GetJsonData();
    return View(myViewModel);
}

public class MyViewModel
{
    //...
    public string JsonString { get; set; }
}

在我的cshtml中

var dataSet = {@(Model.JsonString))};

但是在生成的源代码中,而不是在引号中的字段,它们是 html 编码的,例如&amp;quot;field1&amp;quot;

除了运行字符串替换之外,没有更简洁的方法将JsonResult 转换为string

【问题讨论】:

标签: c# json.net asp.net-core asp.net-core-mvc


【解决方案1】:

字符串 - JavaScriptSerializer:(不能在 ASP.NET Core 中使用)

var json = new JavaScriptSerializer().Serialize(jsonResult.Data);

对象 - Newtonsoft.Json:

var json = JsonConvert.SerializeObject(jsonResult.Data, Formatting.Indented, new KeysJsonConverter(typeof(OBJECT)));

KeysJsonConverter

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;

namespace TestApp.Helpers
{
    // Creates a custom JsonConverter that overrides serialization to add a keys property.

    public class KeysJsonConverter : JsonConverter
    {
        private readonly Type[] _types;

        public KeysJsonConverter(params Type[] types)
        {
            _types = types;
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            JToken t = JToken.FromObject(value);

            if (t.Type != JTokenType.Object)
            {
                t.WriteTo(writer);
            }
            else
            {
                JObject o = (JObject)t;
                IList<string> propertyNames = o.Properties().Select(p => p.Name).ToList();

                o.AddFirst(new JProperty("Keys", new JArray(propertyNames)));

                o.WriteTo(writer);
            }
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter.");
        }

        public override bool CanRead
        {
            get { return false; }
        }

        public override bool CanConvert(Type objectType)
        {
            return _types.Any(t => t == objectType);
        }
    }
}

.cshtml

 var model = @Html.Raw(Json.Encode(Model));

不知道我从哪里得到 KeysJsonConverter,但我已经在我构建的几个项目中使用过它,并且效果很好,感谢最初编写它的人。

【讨论】:

  • 我所知道的 JavaScriptSerializer 不能在 ASP.NET Core 中使用,因为它是系统命名空间的一部分
  • 他无论如何都在使用 Newtonsoft.Json.JsonConvert 方法序列化一个对象,我已经在上面展示了 :) 你是对的,你不能在 ASP.NET Core 中使用 JavaScriptSerializer。但是您可以使用 Newtonsoft.Json 作为 Microsoft.AspNet.Mvc.ModelBinding 的依赖项。
【解决方案2】:

在 ASP.Net 5 中,JsonHelper 可以通过 @Json.Serialize 在剃刀视图中直接使用,因此您可以在剃刀视图中编写类似这样的内容:

var foo = @Json.Serialize(model);

这与手动操作非常相似:

var foo = @Html.Raw(JsonConvert.SerializeObject(model))

这两种情况的问题是 JSON.Net 默认会序列化,但不会对输出进行 XSS 清理。这意味着 model 的内容不会被转义,如果模型依赖于用户输入,则将您的代码留给XSS attacks。例如:

@{
    var model = new
    {
        prop1 = 1,
        prop2 = "</script><script>alert('o hai');</script>",
        prop3 = false
    };
}
var foo = @Json.Serialize(model);

您可以使用Json.Serialize 重载来指定JsonSerializerSettings,因此您可以将StringEscapeHandling 设置为EscapeHtml:

HTML(、&、'、")和控制字符(例如换行符)被转义。

var foo = @Json.Serialize(model, new JsonSerializerSettings { StringEscapeHandling = StringEscapeHandling.EscapeHtml });

PS。我在 github 上提出了一个问题,以在 JsonHelper 中包含默认的 html 转义。

以前版本中使用的方法

如果您搜索有关堆栈溢出的相同问题,您会看到在早期版本的 MVC 中曾经有一个 Json.Encode 帮助器,因此您可以序列化 like this,手动执行 json 序列化。这似乎被 Json.Serialize 取代,默认情况下是不安全的。

还有一个帮助器HttpUtility.JavaScriptStringEncode 可以用来手动编码json 文字。这似乎在 ASP.Net 5 中作为IJavaScriptStringEncoder 存在。唯一的问题是,当与 Newtonsoft.Json(ASP.Net 5 中的默认 json 格式化程序)结合使用时,对于有效的 json 文字(如属性名称中的双引号),它将编码太多。但是它会产生一个有效的字符串,可以在浏览器上用 JSON.parse 解析(所以this approach 应该也可以工作):

@inject Microsoft.Extensions.WebEncoders.IJavaScriptStringEncoder encoder;
...
var foo = JSON.parse("@encoder.JavaScriptStringEncode(JsonConvert.SerializeObject(model))");

还要注意,通过查看最新的源代码,IJavaScriptStringEncoder 在 RC2 中将被替换为 System.Text.Encodings.Web.JavaScriptEncoder

【讨论】:

  • 这就是我一直在寻找的@Json.Serialize(Model);,也是很好的答案。谢谢!!
  • 感谢您的精彩回答!使用带有 JsonSerializerSettings 的 ASP.Net 5 版本可能需要开发人员将 @using Newtonsoft.Json 添加到视图中,以便将 JsonSerializerSettings 的包含命名空间纳入范围。
【解决方案3】:

你可以使用 Newtonsoft

"Newtonsoft.Json": "6.0.8",

然后在控制器中的 JsonResult 对象上

using Newtonsoft.Json;

var jsonResult = Json(myObject);

string jsonString= JsonConvert.SerializeObject(jsonResult.Value);

【讨论】:

    猜你喜欢
    • 2014-05-06
    • 2011-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多