2015-01-26 11 views
7

Ich verwende Datensatztypen in einem F # -Projekt, das ich einem C# WebApi-Projekt aussetze. Zum Beispiel:F #, Json, WebApi Serialisierung von Optionstypen

type Account = {Amount:float; Number:int; Holder:string} 

Basierend auf this Post und this Post wird die json serializaing richtig.

{"Amount":100.0,"Number":1,"Holder":"Homer"} 

Allerdings, wenn ich in einem Optionstyp auf den Datensatz hinzufügen,

type Account = {Amount:float; Number:int; Holder:string option } 

die json wird unglued.

{"Amount":100.0,"Number":1,"Holder":{"Case":"Some","Fields":["Homer"]}} 

Ich mag die json das gleiche wie der nicht-Option Typen Datensatz suchen mit dem Serializer intelligent genug, um die Werte zu übernehmen und sie in/aus der Option automatisch eingeben.

Hat jemand zu diesem Zweck einen benutzerdefinierten Formatierer gebaut? Gibt es etwas, das ich vermisse?

Dank

Antwort

5

Eine benutzerdefinierte Json.NET-Konverter, der Optionstypen und sorten diskriminiert Gewerkschaften Griffe vorhanden ist (oder zumindest behauptet, ich die Option Typ Fall nur getestet). Es kann here gefunden werden.

Verbrauch:

let act = {Amount= 100.0; Number= 1; Holder= Some "Homer"} 
let json = JsonConvert.SerializeObject(act, new IdiomaticDuConverter()) 
+0

Wie würde ich hinzufügen, dies die WebApiConfig in einem C# -Projekt? Gibt es eine Möglichkeit, dem DefaultContractResolver einen Konverter hinzuzufügen? –

+0

NM -> hab es. formatter.SerializerSettings.Converters.Add (neuer IdiomaticDuConverter()); –

11

habe ich versucht, den Konverter in der anderen Antwort verknüpft ist, und ich wusste nicht, wie die Ausgabe anderer DUs, die nicht Option war. Stattdessen sollten Sie möglicherweise nur das Verhalten des Optionstyps ändern und nicht alle DUs.

Ich fand diesen Konverter, der nur das Verhalten für den Optionstyp ändern wird, um null auf der None-Option zu rendern, andernfalls den Wert. Der ursprüngliche Code/Autor Info kann here gefunden werden.

open System 
open Microsoft.FSharp.Reflection 
open Newtonsoft.Json 
open Newtonsoft.Json.Converters 

type OptionConverter() = 
    inherit JsonConverter() 

    override x.CanConvert(t) = 
     t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<option<_>> 

    override x.WriteJson(writer, value, serializer) = 
     let value = 
      if value = null then null 
      else 
       let _,fields = FSharpValue.GetUnionFields(value, value.GetType()) 
       fields.[0] 
     serializer.Serialize(writer, value) 

    override x.ReadJson(reader, t, existingValue, serializer) =   
     let innerType = t.GetGenericArguments().[0] 
     let innerType = 
      if innerType.IsValueType then (typedefof<Nullable<_>>).MakeGenericType([|innerType|]) 
      else innerType   
     let value = serializer.Deserialize(reader, innerType) 
     let cases = FSharpType.GetUnionCases(t) 
     if value = null then FSharpValue.MakeUnion(cases.[0], [||]) 
     else FSharpValue.MakeUnion(cases.[1], [|value|]) 

den Konverter ist die gleiche wie andere Antwort:

let json = JsonConvert.SerializeObject(myObj, new OptionConverter()) 
Verwandte Themen