Johnson Cheung
Johnson Cheung

Reputation: 107

How to parse string to any F# data?

In F#, any data can be stringify by function sprintf as following:

type someKindOfDataType = ...
let data : someKindOfDataType = ...
sprintf "%A" data

Can we have a reversal function to parse a string back to someKindOfDataType, like following:?

let parse<'someKingOfDataType> (s:string) : someKindOfDataType = ....

just like JSON.parse in javascript?

Upvotes: 2

Views: 2171

Answers (2)

Gus
Gus

Reputation: 26174

The standard .NET way is that normally you'll use a Parse or TryParse method in the class of the type you're trying to parse.

But in F# the TryParse function is not very friendly, since it uses an output parameter, still the F# compiler allows you to see it as a tuple, which makes things better but still you'll expect to get an option, here's an example:

let a = Int32.Parse "5"
let b = 
    match Int32.TryParse "5" with
    | true, value -> Some value
    | _           -> None

If you want to use a library F#+ has both functions parse and tryParse which does all the above for you:

#r @"FSharpPlus.dll"
open FSharpPlus
open System

let (a:int) = parse "5"
let (b:int option) = tryParse "5"
let (c: Net.IPAddress option) = tryParse "10.0.0.1"

// val a : int = 5
// val b : int option = Some 5
// val c : Net.IPAddress option = Some 10.0.0.1

It works as long as the type has either Parse or TryParse defined.

Upvotes: 2

TheQuickBrownFox
TheQuickBrownFox

Reputation: 10624

You are describing what is normally referred to as serialisation - converting from an in-memory data structure to a representation that can be transmitted over a network, which could be XML, JSON, binary etc. - and deserialisation - the reverse.

sprintf "%A" is designed to give a convenient visual representation of data, usually only for the purposes of development as opposed to in production. It does not actually do serialisation, since there is no way to deserialise.

If you want to serialise F# data to a string I would recommend using JSON via library such as Newtonsoft.Json.

Note that this will not produce strings that look similar to F# source code like sprintf "%A" does because the purpose is different. An example:

Newtonsoft.Json.JsonConvert.SerializeObject [|Some 3; None|]
// """[{"Case":"Some","Fields":[3]},null]"""

Newtonsoft.Json.JsonConvert.DeserializeObject<int option []> """[{"Case":"Some","Fields":[3]},null]"""
// [|Some 3; None|]

You need to provide the type to deserialise to and this operation may throw an exception if the string doesn't represent a valid instance of that type.

Upvotes: 2

Related Questions