JSON сериализует объект с параметром функции

У меня есть этот объект С#:

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

Мне нужно, чтобы JSON сериализовал его, чтобы передать браузеру в ajax-вызов. Я использую JavascriptSerializer, но он сериализуется в следующем JSON:

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

но мне нужно:

{"username":"andrey", "callback": function(self) { return function() {self.doSomething()} (this) }}
  • нет кавычек вокруг определения функции.

Прямо сейчас, когда объект JSON попадает в браузер и создается, параметр 'callback' не является функцией, а строкой. Любая идея, как ее исправить, желательно на стороне сервера?

Ответ 1

Это поведение преднамеренное. JSON не должен включать ничего, кроме данных - в вашем случае исполняемая функция. Браузер будет раскрывать огромные угрозы безопасности, если данные могут возвращаться с сервера в формате JSON, который при выполнении запускает произвольные функции (которые могут украсть информацию, перенаправить пользователя на вредоносный сайт и т.д.)

Ранние реализации JSON полагаются на то, что возвращаемые данные могут быть просто выполнены с помощью eval(), чтобы вернуть объект. Тем не менее, люди почти сразу поняли, что это открывает огромные угрозы безопасности и с тех пор пытается справиться с этим. Поэтому перед стандартизованным объектом JSON люди перестали помещать необработанные данные JSON в eval() и вместо этого использовали библиотеки разбора JSON.

Объект JSON всегда будет сериализовать объект только в данных. Это по дизайну. Стандартный формат JSON не может представлять исполняемую функцию.

Теперь вы можете легко преобразовать этот обратный вызов в браузер в функцию, передав его через eval(). Однако не делать этого. Вы просто открываете для взлома.

На стороне сервера современные браузеры предназначены для предотвращения этой точной вещи, т.е. отправки данных из браузера, который содержит исполняемую функцию.

Ответ 2

Я пытался добиться чего-то подобного. В моем случае я использовал синтаксис MVC Razor, пытаясь сгенерировать объект json с функцией, переданной с использованием @<text> синтаксис.

Мне удалось получить желаемый результат с помощью библиотеки Json.net(используя JsonConvert и JRaw).

Пример:

// 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);

Это должно дать вам объект json с функцией (вместо функции в строке).

Сообщение: Как сериализовать функцию для json (используя razor @<text> )