1

I want to serialize a Plotly chart in F# into JSON string so it can be passed as a payload through a HTTP request.

In theory, this should be trivial as the Plotly.NET documentation states, "Plotly.NET is a .NET wrapper for creation of plotly charts. This means that, under the hood, all functionality creates JSON objects that can be rendered by plotly".

From having used Plotly in Python, the the way to do this is:

json.dumps(obj=Figure(), cls=utils.PlotlyJSONEncoder)

Is there an equivalent method for F#?

PatJon6
  • 13
  • 5

1 Answers1

0

In general, note that json creation in Plotly.NET is a one-way road, you can not deserialize the json objects into Plotly.NET types easily.

However, since you only asked for serialization only, one way is converting the GenericChart (which is a Union, therefore you cannot serialize it directly) to a Figure, and then serializing it (note that i use UseDefaults=false to reduce json size for this example, otherwise it would include large amounts of template stuff):

open Plotly.NET
open Newtonsoft.Json

let settings = JsonSerializerSettings(ReferenceLoopHandling = ReferenceLoopHandling.Serialize)

Chart.Point([1,2], UseDefaults = false) 
|> GenericChart.toFigure
|> fun c -> JsonConvert.SerializeObject(c, settings)

result:

{"data":[{"type":"scatter","mode":"markers","x":[1],"y":[2],"marker":{},"line":{}}],"layout":{},"frames":[]}

this does not include the config object though. if you want to include that, there is currently no easy built-in for that, as internally the respective charts are deconstructed into data, layout, and config objects and then serialized and injected into html.

So you could do this if you need the config object serialized:

type ChartDTO = {
    data: Trace list
    layout: Layout
    config: Config
}

Chart.Point([1,2], UseDefaults = false)
|> fun c ->
    {
        data = c |> GenericChart.getTraces
        layout = c |> GenericChart.getLayout
        config = c |> GenericChart.getConfig
    }

|> fun c -> JsonConvert.SerializeObject(c, settings)

result:

{"data":[{"type":"scatter","mode":"markers","x":[1],"y":[2],"marker":{},"line":{}}],"layout":{},"config":{}}

I agree that this is harder than it should be though, so I opened #399 to track this. Ideally, there should be GenericChart.toFigureJson and GenericChart.toJson, and the internal serializer settings should be exposed instead of being private.

kMutagene
  • 177
  • 10
  • Thanks! This looks good. My idea was to create the charts in F# and then pass them to the browser, where the they can be rendered by Plotly.js. But honestly, I think it just might be easier to create the entire chart in the browser and just pass the data through HTTP. – PatJon6 Jul 11 '23 at 18:52
  • If you can serve full web pages, you could just create the full html page and return that, or embed the chart html in your page template. The respective functions would be `Chart.toChartHTML` for the chart only, and `Chart.toEmbeddedHTML` for a full page – kMutagene Jul 12 '23 at 06:37
  • I want the charts to re-render dynamically without re-sending the HTML, which is my main goal. Thanks for the tip, I might use it another time. – PatJon6 Jul 12 '23 at 18:25