我知道如何使用可變對象在F#中進行序列化,但是有沒有辦法使用XmlSerializer或DataContractSerializer使用記錄類型來序列化/反序列化?貌似有一種方法可以使用KnownType屬性識別聯合做到這一點,但是我正在尋找一種方式來使用非可變記錄沒有默認構造函數...記錄類型的F#序列化
回答
樣品code for reading data from Freebase由喬莫·費希爾使用DataContractJsonSerializer
到將數據加載到不可變的F#記錄中。記錄的聲明,他使用這個樣子的:
[<DataContract>]
type Result<'TResult> = { // '
[<field: DataMember(Name="code") >]
Code:string
[<field: DataMember(Name="result") >]
Result:'TResult // '
[<field: DataMember(Name="message") >]
Message:string }
這裏的關鍵點是,在DataMember
屬性附加到這實際上是用來存儲數據,而不是隻讀屬性的基礎字段F#編譯器生成(使用屬性上的field:
修飾符)。
我不是100%肯定這是否會與其他類型的序列化(可能不是)工作,但它可能是一個有用的指針開始...
編輯我不知道如果我失去了一些東西,但以下基本示例工作正常,我:
module Demo
#r "System.Runtime.Serialization.dll"
open System.IO
open System.Text
open System.Xml
open System.Runtime.Serialization
type Test =
{ Result : string[]
Title : string }
do
let sb = new StringBuilder()
let value = { Result = [| "Hello"; "World" |]; Title = "Hacking" }
let xmlSerializer = DataContractSerializer(typeof<Test>);
xmlSerializer.WriteObject(new XmlTextWriter(new StringWriter(sb)), value)
let sr = sb.ToString()
printfn "%A" sr
let xmlSerializer = DataContractSerializer(typeof<Test>);
let reader = new XmlTextReader(new StringReader(sr))
let obj = xmlSerializer.ReadObject(reader) :?> Test
printfn "Reading: %A" obj
EDIT 2如果你想生成XML更清潔,那麼你可以添加的屬性是這樣的:
[<XmlRoot("test")>]
type Test =
{ [<XmlArrayAttribute("results")>]
[<XmlArrayItem(typeof<string>, ElementName = "string")>]
Result : string[]
[<XmlArrayAttribute("title")>]
Title : string }
這是一個開始,但生成的xml不是「乾淨的」,我的意思是標籤就像「FSI_0132」。測試「,而不是測試和Title_x0040_而不是標題。我也看起來像不能使用[
命名空間「FSI_0132」由F#Interactive生成 - 在編譯後的代碼中,它將替換爲實際的命名空間。不知道的屬性名稱,但 – 2010-10-27 17:12:53
@Joel:對,我明白,但我的目標是有乾淨的XML沒有任何名稱空間的信息,就像您如果你試圖在.NET – Alex 2010-10-27 17:24:32
您可以使用這一系列的註解上的類的屬性設置格式的XML:
[XmlRoot("root")]
[XmlElement("some-element")]
[XmlAttribute("some-attribute")]
[XmlArrayAttribute("collections")]
[XmlArrayItem(typeof(SomeClass), ElementName = "item")]
我使用的屬性在我的C#類,但在F#反序列化(C#類INA引用LIB)。
在F#:
use file = new FileStream(filePath, FileMode.Open)
let serializer= XmlSerializer(typeof<SomeClass>)
let docs = serializer.Deserialize file :?> SomeClass
這很酷,但要求是使用非可變類型,所以這方法將無法正常工作,因爲該類將有可變字段 – Alex 2010-10-27 20:21:33
它不使用的XmlSerializer或DataContractSerializer的,但Json.NET 6.0 includes nice F# support.
它看起來像這樣:
type TestTarget =
{ a: string
b: int }
[<TestFixture>]
type JsonTests() =
[<Test>]
member x.``can serialize``() =
let objectUnderTest = { TestTarget.a = "isa"; b = 9 }
let jsonResult: string = Newtonsoft.Json.JsonConvert.SerializeObject(objectUnderTest)
printfn "json is:\n%s" jsonResult
let xmlResult = Newtonsoft.Json.JsonConvert.DeserializeXmlNode(jsonResult, "root")
printfn "xml is:\n%s" (xmlResult.OuterXml)
let jsonRoundtrip = Newtonsoft.Json.JsonConvert.DeserializeObject<TestTarget>(jsonResult)
printfn "json roundtrip: %A" jsonRoundtrip
let xmlAsJson = Newtonsoft.Json.JsonConvert.SerializeXmlNode(xmlResult, Newtonsoft.Json.Formatting.Indented, true)
printfn "object -> json -> xml -> json:\n%A" xmlAsJson
let xmlRoundtrip = Newtonsoft.Json.JsonConvert.DeserializeObject<TestTarget>(xmlAsJson)
printfn "xml roundtrip:\n%A" xmlRoundtrip
Assert.That(true, Is.False)
()
json is:
{"a":"isa","b":9}
xml is:
<root><a>isa</a><b>9</b></root>
json roundtrip: {a = "isa";
b = 9;}
object -> json -> xml -> json:
"{
"a": "isa",
"b": "9"
}"
xml roundtrip:
{a = "isa";
b = 9;}
真棒,用於顯示使用記錄類型的方式,而不需要'[
我發現這並不尊重成員名稱的大小寫敏感性(它們總是轉換爲小寫)。 – 2015-10-05 17:17:57
與F#3.0開始,記錄的系列化現在通過將CliMutableAttribute
應用於該類型支持類型。例如:
[<CLIMutable>]
type MyRecord = { Name : string; Age : int }
此示例來自http://blogs.msdn.com/b/fsharpteam/archive/2012/07/19/more-about-fsharp-3.0-language-features.aspx,其包括該功能的討論中和在其他三個新的功能採取F#3.0:三重引用的字符串,自動屬性,和未使用的變量的警告。
- 1. 序列化F#選項類型
- 2. 序列化f#代數數據類型
- 3. printf類型的日誌記錄F#
- 4. F#泛型記錄
- 5. 可變F#記錄的二進制序列化
- 6. Rails獲取序列化模型記錄
- 7. 簡化F#記錄分配
- 8. F#記錄和列表排序
- 9. 無法序列化瞬態記錄類型postgres
- 10. 從參數化記錄類型實例化Clojurescript中的記錄?
- 11. 序列化不帶類型標記的類型
- 12. 將F#的記錄類型序列化爲JSON在每個屬性後包含「@」字符
- 13. 「序列化」 VHDL記錄
- 14. 如何使用F#Union類型與Servicestack JSON序列化?
- 15. 序列化數據類型以通過F#網絡使用
- 16. F#界面/抽象類型和序列化
- 17. F#和NUnit:測試失敗時記錄類型的結構化輸出
- 18. 是否將F#記錄類型實現爲結構體或類?
- 19. F#記錄,這
- 20. F#對尚未分配值的記錄排序序列
- 21. MonoTouch:如何序列化未標記爲可序列化的類型(如CLLocation)?
- 22. 何時使用歧視聯盟與F#中的記錄類型
- 23. F#:一個複雜的記錄類型和一個DataGridView
- 24. F#聯盟類型列表
- 25. F#多維陣列類型
- 26. 更改結構化/記錄陣列的類型
- 27. 反序列化與F#
- 28. 簡化記錄類型Id鏈接
- 29. 記錄列表的TypeScript數據類型
- 30. OCaml序列化與類型
我結束了剛剛使用XML解析,這在我的情況,以及我試圖沒有工作產生乾淨的XML,即使托馬斯的建議使用System.Xml.Serialization的屬性,我的懷疑是它是不會工作,但我決定嘗試反正他們沒有,我相信因爲datacontract的命名空間忽略了這些。我的要求是在這個練習中使用非可變記錄,但是如果你的目標只是xml序列化,那麼它就和以任何其他.net語言使用它沒什麼兩樣,只需創建類,裝飾它們並使用XmlSerializer,它就可以工作。 – Alex 2010-11-29 16:27:29