Hmm đây là một vấn đề phức tạp. Tôi giả sử điều này:
{"map":
{"Momentum":12, "Corporate":3, "Catalyst":1},
"javaClass":"java.util.HashMap"}
có thể chứa một số lượng trường thay đổi. Và trong ký hiệu JSON chuyển thành một đối tượng (các đối tượng javascript về cơ bản (hoặc rất giống) với các bản đồ). Tôi không biết nếu điều này sẽ dịch sang F # trực tiếp.
Nó có thể được ngăn chặn không được phép bằng cách gõ F # tĩnh so với gõ động của javascript.
bạn có thể phải tự viết thói quen chuyển đổi.
Ok có được một vài lỗi nhỏ trong hợp đồng dữ liệu cho phép xác định lại JsonMap và loại bỏ các "JavaClass" thuộc tính vì nó không có trong mẫu JSON thứ cung cấp (đó là một mức độ cao hơn lên), và nó trông như thể keyvaulepair với tôi không serializing, vì vậy cho phép xác định loại của chúng ta:
type JsonKeyValuePair<'T, 'S> = {
[<DataMember>]
mutable key : 'T
[<DataMember>]
mutable value : 'S
}
type JSONMap<'T, 'S> = {
[<DataMember>]
mutable map : JsonKeyValuePair<'T, 'S> array
}
và tạo một hàm deserialize:
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
()
tôi có thể deserialize một str ing vào cấu trúc đối tượng thích hợp. Hai điều tôi muốn thấy được trả lời là
1) tại sao .NET buộc tôi phải thêm @ ký tự sau tên trường? 2) cách tốt nhất để thực hiện chuyển đổi là gì? Tôi đoán một cây cú pháp trừu tượng biểu diễn cấu trúc JSON có thể là cách để đi, và sau đó phân tích cú pháp đó thành chuỗi mới. Tôi không siêu quen thuộc với AST và phân tích cú pháp của họ mặc dù.
Có lẽ một trong các chuyên gia F # có thể trợ giúp hoặc đưa ra một bản dịch tốt hơn?
cuối cùng cộng lại trong các loại quả:
[<DataContract>]
type Result<'T> = {
[<DataMember>]
mutable javaClass: string
[<DataMember>]
mutable result: 'T
}
và một chức năng bản đồ chuyển đổi (công trình trong trường hợp này - nhưng có nhiều khu vực của yếu bao gồm các định nghĩa đồ đệ quy vv):
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
Nó vẫn inisits trên dấu @ ở những nơi khác nhau - mà tôi không nhận được ...
cách thêm chuyển đổi w/workaround cho vấn đề dấu và
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
thêm:
[<DataContract>]
trên các hồ sơ sửa chữa các vấn đề Ký hiệu &.
tôi nhận thấy rằng khi tôi lưu trữ các loại F # Ghi vào RavenDB, họ sẽ được lưu trữ với tên thuộc tính thường xuyên, và tên thuộc tính tương tự tiếp theo là một dấu hiệu @. Tôi nghi ngờ phiên bản @ là trường sao lưu cho thuộc tính công khai trong loại bản ghi. Tạo lớp của riêng tôi thay vì sử dụng một bản ghi đã loại bỏ các thuộc tính @ bổ sung - bạn có thể phải làm một cái gì đó như thế. –