Diego
Diego

Reputation: 1018

Send javascript function over json using Json.NET lib

I am attempting to send a javascript function over json in .Net and I am having trouble serializing the object.

The javascript library Highcharts uses the following function on their json object to customize the chart tooltip.

tooltip: {
         formatter: function() {
            var s;
            if (this.point.name) { // the pie chart
               s = ''+
                  this.point.name +': '+ this.y +' fruits';
            } else {
               s = ''+
                  this.x  +': '+ this.y;
            }
            return s;
         }
      },

I am attempting to use the popular Json.NET library using an anonymous type to create such object but all my efforts serialize to a string in the end. Any help is appreciated. Thanks!

Upvotes: 4

Views: 3662

Answers (5)

Tomasz Polachowski
Tomasz Polachowski

Reputation: 191

As of Newtonsoft.Json 12.0.1 (11/27/2018), the standard solution for this is to use JRaw type.

public class JavaScriptSettings
{
    public JRaw OnLoadFunction { get; set; }
    public JRaw OnUnloadFunction { get; set; }
}

JavaScriptSettings settings = new JavaScriptSettings
{
    OnLoadFunction = new JRaw("OnLoad"),
    OnUnloadFunction = new JRaw("function(e) { alert(e); }")
};

string json = JsonConvert.SerializeObject(settings, Formatting.Indented);

Console.WriteLine(json);
// {
//   "OnLoadFunction": OnLoad,
//   "OnUnloadFunction": function(e) { alert(e); }
// }

Source

Upvotes: 3

Jamieson Rhyne
Jamieson Rhyne

Reputation: 467

I like the answer from ObOzOne, but it can be a little simpler by just using the WriteRawValue. For example:

public class FunctionSerializer : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(string));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        string valueAsString = Convert.ToString(value);

        if (!string.IsNullOrWhiteSpace(valueAsString))
            writer.WriteRawValue(valueAsString);
    }
}

And then on your property that you want to serialize:

[JsonConverter(typeof(FunctionSerializer))]
public string HideExpression { get; set; }

Upvotes: 4

ObOzOne
ObOzOne

Reputation: 11

I was inspired by the example above by generic methods :

public class FunctionConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(String));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, String.Concat("<Function>", value, "</Function>"));
    }
}

public static class JsonObjectExtensions
{
    public static String CleanJson(this String s)
    {
        return s.Replace("\"<Function>", "").Replace("</Function>\"", "");
    }
}

public partial class JsonObject
{
    public String ToJson()
    {
        return JsonConvert.SerializeObject(this).CleanJson();
    }
}

And the model data :

public class ConfigModel : JsonObject
{
    [JsonProperty("altFormat", NullValueHandling = NullValueHandling.Ignore)]
    public String altFormat { get; set; }

    [JsonProperty("onClose", NullValueHandling = NullValueHandling.Ignore)]
    [JsonConverter(typeof(FunctionConverter))]
    public String onClose { get; set; }

}

Upvotes: 1

Dan Pettersson
Dan Pettersson

Reputation: 743

A bit of a hack but I solved it this way:

string linkUrl = "http://www.google.com";
dynamic result = new ExpandoObject();
result.render = "FUNCfunction (data) { return '<a href=\"" + linkUrl + "\">' + data + '</a>'; }FUNC";
var json = Newtonsoft.Json.JsonConvert.SerializeObject(result).Replace("\"FUNC", "").Replace("FUNC\"", "")

By surrounding my function with the FUNC placeholders and then replacing "FUNC and FUNC" with emtpy string in the generated json I get the function in my json object.

Upvotes: 2

Aliostad
Aliostad

Reputation: 81660

JSON as the name implies, is only an object notation and suitable for transferring state as object.

If you need to send JavaScript code itself, you can use a JavaScriptResult in ASP NET MVC if you are using it.

If you are using ASP NET Web Forms, have an ASPX file which writes the JavaScript straight to the response. Make sure you change the ContentType to text/javascript.

Upvotes: 3

Related Questions