嗯,這是一個複雜的問題。我假設:
{"map":
{"Momentum":12, "Corporate":3, "Catalyst":1},
"javaClass":"java.util.HashMap"}
可能包含可變數量的字段。而在JSON中,符號轉換爲對象(javascript對象基本上(或者非常類似於地圖))。我不知道這是否會直接轉換爲F#。
它可能會阻止F#靜態類型與JavaScript的動態類型的不匹配。
您可能必須自己編寫轉換例程。
確定有一對情侶在所述數據契約小錯誤的允許重新定義JsonMap併除去「javaclass」屬性,因爲它是沒有設置第JSON樣品(它是一個較高的水平上),並它看起來好像keyvaulepair我沒有序列化,所以讓我們自己定義的類型:
type JsonKeyValuePair<'T, 'S> = {
[<DataMember>]
mutable key : 'T
[<DataMember>]
mutable value : 'S
}
type JSONMap<'T, 'S> = {
[<DataMember>]
mutable map : JsonKeyValuePair<'T, 'S> array
}
,並創建一個反序列化功能:
let internal deserializeString<'T> (json: string) : 'T =
let deserializer (stream : MemoryStream) =
let jsonSerializer
= Json.DataContractJsonSerializer(
typeof<'T>)
let result = jsonSerializer.ReadObject(stream)
result
let convertStringToMemoryStream (dec : string) : MemoryStream =
let data = Encoding.Unicode.GetBytes(dec);
let stream = new MemoryStream()
stream.Write(data, 0, data.Length);
stream.Position <- 0L
stream
let responseObj =
json
|> convertStringToMemoryStream
|> deserializer
responseObj :?> 'T
let run2() =
let json = "{\"[email protected]\":[{\"[email protected]\":\"a\",\"[email protected]\":1},{\"[email protected]\":\"b\",\"[email protected]\":2}]}"
let o = deserializeString<JSONMap<string, int>> json
()
我能夠反序列化STR進入適當的對象結構。我想看到的兩件事情是:
1)爲什麼.NET迫使我在字段名稱後追加@字符? 2)什麼是轉換的最佳方式?我猜想代表JSON結構的抽象語法樹可能是要走的路,然後將其解析爲新的字符串。儘管我不太熟悉AST和他們的解析。
也許其中一位F#專家可能能夠幫助或提出更好的翻譯方案?
的結果類型最後加回:
[<DataContract>]
type Result<'T> = {
[<DataMember>]
mutable javaClass: string
[<DataMember>]
mutable result: 'T
}
和轉換地圖功能(在這種情況下的作品 - 但有弱點的許多領域,包括遞歸地圖定義等):
let convertMap (json: string) =
let mapToken = "\"map\":"
let mapTokenStart = json.IndexOf(mapToken)
let mapTokenStart = json.IndexOf("{", mapTokenStart)
let mapObjectEnd = json.IndexOf("}", mapTokenStart)
let mapObjectStart = mapTokenStart
let mapJsonOuter = json.Substring(mapObjectStart, mapObjectEnd - mapObjectStart + 1)
let mapJsonInner = json.Substring(mapObjectStart + 1, mapObjectEnd - mapObjectStart - 1)
let pieces = mapJsonInner.Split(',')
let convertPiece state (piece: string) =
let keyValue = piece.Split(':')
let key = keyValue.[0]
let value = keyValue.[1]
let newPiece = "{\"key\":" + key + ",\"value\":" + value + "}"
newPiece :: state
let newPieces = Array.fold convertPiece [] pieces
let newPiecesArr = List.toArray newPieces
let newMap = String.Join(",", newPiecesArr)
let json = json.Replace(mapJsonOuter, "[" + newMap + "]")
json
let json = "{\"id\":1, \"result\": {\"map\": {\"Momentum\":12, \"Corporate\":3, \"Catalyst\":1}, \"javaClass\":\"java.util.HashMap\"} } "
printfn <| Printf.TextWriterFormat<unit>(json)
let json2 = convertMap json
printfn <| Printf.TextWriterFormat<unit>(json2)
let obj = deserializeString<Result<JSONMap<string,int>>> json2
它仍然在各個地方的@標誌上徘徊 - 我不明白...
增加轉換瓦特/解決方法的符號問題
let convertMapWithAmpersandWorkAround (json: string) =
let mapToken = "\"map\":"
let mapTokenStart = json.IndexOf(mapToken)
let mapObjectEnd = json.IndexOf("}", mapTokenStart)
let mapObjectStart = json.IndexOf("{", mapTokenStart)
let mapJsonOuter = json.Substring(mapTokenStart , mapObjectEnd - mapTokenStart + 1)
let mapJsonInner = json.Substring(mapObjectStart + 1, mapObjectEnd - mapObjectStart - 1)
let pieces = mapJsonInner.Split(',')
let convertPiece state (piece: string) =
let keyValue = piece.Split(':')
let key = keyValue.[0]
let value = keyValue.[1]
let newPiece = "{\"[email protected]\":" + key + ",\"[email protected]\":" + value + "}"
newPiece :: state
let newPieces = Array.fold convertPiece [] pieces
let newPiecesArr = List.toArray newPieces
let newMap = String.Join(",", newPiecesArr)
let json = json.Replace(mapJsonOuter, "\"[email protected]\":[" + newMap + "]")
json
let json = "{\"id\":1, \"result\": {\"map\": {\"Momentum\":12, \"Corporate\":3, \"Catalyst\":1}, \"javaClass\":\"java.util.HashMap\"} } "
printfn <| Printf.TextWriterFormat<unit>(json)
let json2 = convertMapWithAmpersandWorkAround json
printfn <| Printf.TextWriterFormat<unit>(json2)
let obj = deserialize<Result<JSONMap<string,int>>> json2
補充說:
[<DataContract>]
上面記錄修復和號問題。
我注意到,當我保存F#記錄類型爲RavenDB,它們將被存儲與普通的屬性名稱,後跟一個@符號相同的屬性名稱。我懷疑@版本是記錄類型中公共屬性的支持字段。創建我自己的類,而不是使用記錄擺脫了額外的@屬性 - 你可能不得不這樣做。 – 2010-11-17 18:52:49