简体   繁体   English

JSON 序列化具有函数参数的对象

[英]JSON serializing an object with function parameter

I have this C# object:我有这个 C# 对象:

var obj = new {
    username = "andrey",
    callback = "function(self) { return function() {self.doSomething()} (this) }"
}

I need to JSON serialize it to pass to the browser in ajax call.我需要 JSON 序列化它以在 ajax 调用中传递给浏览器。 I use JavascriptSerializer, but it serializes to the following JSON:我使用 JavascriptSerializer,但它序列化为以下 JSON:

{"username":"andrey", "callback": "function(self) { return function() {self.doSomething()} (this) }"}

but what I need is:但我需要的是:

{"username":"andrey", "callback": function(self) { return function() {self.doSomething()} (this) }}
  • no quotes around function definition.函数定义周围没有引号。

Right now, when the JSON object gets to the browser and is created, the 'callback' parameter is not a function but a string.现在,当 JSON 对象到达浏览器并被创建时,'callback' 参数不是一个函数而是一个字符串。 Any idea how to fix it, preferably on the server side?知道如何修复它,最好是在服务器端?

I was trying to accomplish something similar.我试图完成类似的事情。 In my case I was using MVC Razor syntax trying to generate a json object with a function passed in using the @<text> syntax.在我的例子中,我使用 MVC Razor 语法试图生成一个 json 对象,其中包含一个使用 @<text> 语法传入的函数。

I was able to get the desired output using the Json.net library (using JsonConvert and JRaw).我能够使用 Json.net 库(使用 JsonConvert 和 JRaw)获得所需的输出。

Example:例子:

// set the property value using JRaw
var obj = new {
    username = "andrey",
    callback = new JRaw("function(self) { return function() {self.doSomething()} (this) }")
}
// and then serialize using the JsonConvert class
var jsonObj = JsonConvert.SerializeObject(obj);

That should get you the json object with the function (instead of the function in a string).这应该为您提供带有函数的 json 对象(而不是字符串中的函数)。

Post: How to serialize a function to json (using razor @<text>)帖子: 如何将函数序列化为 json(使用 razor @<text>)

This behavior is deliberate.这种行为是故意的。 JSON should not include anything that is not data -- in your case an executable function. JSON 不应该包含任何不是数据的东西——在你的情况下是一个可执行函数。 The browser will be opening up to huge security risks if data can come back from a server in JSON format that, when executed, will run arbitrary functions (that can steal info, redirect the user to a malicious site etc.)如果数据可以以 JSON 格式从服务器返回,浏览器将面临巨大的安全风险,该服务器在执行时将运行任意功能(可以窃取信息,将用户重定向到恶意站点等)

Early implementations of JSON rely on the fact that data returned back can be simply executed via eval() to get back an object. JSON 的早期实现依赖于这样一个事实,即返回的数据可以通过 eval() 简单地执行以获取一个对象。 However, people almost immediately realized that this opens up huge security risks and have been trying to handle it since.然而,人们几乎立即意识到这会带来巨大的安全风险,并一直在努力应对。 That's why, before the standardized JSON object, people stopped putting raw JSON data into eval() and used JSON parsing libraries instead.这就是为什么在标准化 JSON 对象出现之前,人们不再将原始 JSON 数据放入 eval() 中,而是使用 JSON 解析库。

The JSON object will always serialize an object into data only. JSON 对象将始终仅将对象序列化为数据。 This is by design.这是设计使然。 THe standardized JSON format has no way to represent an executable function.标准化的 JSON 格式无法表示可执行函数。

Now, you can easily convert that callback on a browser into a function by passing it through to eval().现在,您可以通过将它传递给 eval() 来轻松地将浏览器上的回调转换为函数。 However, don't do it .但是,不要这样做 You're just opening yourself up for hacking.你只是在为黑客敞开心扉。

On the server side, modern browsers are designed to prevent this exact thing from happening -- ie data being sent from a browser that contains an executable function.在服务器端,现代浏览器旨在防止这种情况发生——即从包含可执行功能的浏览器发送数据。

You can make use of the constructor of the Function object.您可以使用 Function 对象的构造函数。 See https://developer.mozilla.org/nl/docs/Web/JavaScript/Reference/Global_Objects/Function .请参阅https://developer.mozilla.org/nl/docs/Web/JavaScript/Reference/Global_Objects/Function

In your json you set the callback property to a string array that describes the Function constructor parameters.在您的 json 中,您将回调属性设置为描述函数构造函数参数的字符串数组。 Then when the json data has arrived on the client you have to convert the Array to an instance of the Function object.然后当 json 数据到达客户端时,您必须将 Array 转换为 Function 对象的实例。

This way you can have the function implementation details in your back database instead of hardcoded in source code.通过这种方式,您可以在后台数据库中获得函数实现细节,而不是在源代码中进行硬编码。

const json = '{"username":"andrey","callback":["self","return self.doSomething()"]}';

//Parse the json to an object
const object = JSON.parse(json);

//Convert the callback property from Array to Function
object["callback"] = new Function(...object["callback"]);

//Create a parameter for calling the Function
var self = {
    doSomething() {
        console.log("Do something called");
    }
}

//Call the function
object["callback"](self);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM