嗯,这是一个复杂的问题。我假设:
{"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