基本上我想要一个构造来处理序列化为JSON和格式化的xml。记录很好地用于序列化到/从json。但是XmlSerializer需要一个无参数的construtor。我真的不想完成为这些构造构建类对象的练习(仅限原理)。我希望有一些快捷方式可以将无参数构造函数放到记录上(可能带有一个wioth语句或其他东西)。我无法表现出来 - 社区中有没有人有运气?
module JSONExample
open System
open System.IO
open System.Net
open System.Text
open System.Web
open System.Xml
open System.Security.Authentication
open System.Runtime.Serialization //add assemnbly reference System.Runtime.Serialization System.Xml
open System.Xml.Serialization
open System.Collections.Generic
[<DataContract>]
type ChemicalElementRecord = {
[<XmlAttribute("name")>]
[<field: DataMember(Name="name") >]
Name:string
[<XmlAttribute("name")>]
[<field: DataMember(Name="boiling_point") >]
BoilingPoint:string
[<XmlAttribute("atomic-mass")>]
[<field: DataMember(Name="atomic_mass") >]
AtomicMass:string
}
[<XmlRoot("freebase")>]
[<DataContract>]
type FreebaseResultRecord = {
[<XmlAttribute("code")>]
[<field: DataMember(Name="code") >]
Code:string
[<XmlArrayAttribute("results")>]
[<XmlArrayItem(typeof<ChemicalElementRecord>, ElementName = "chemical-element")>]
[<field: DataMember(Name="result") >]
Result: ChemicalElementRecord array
[<XmlElement("message")>]
[<field: DataMember(Name="message") >]
Message:string
}
let getJsonFromWeb() =
let query = "[{'type':'/chemistry/chemical_element','name':null,'boiling_point':null,'atomic_mass':null}]"
let query = query.Replace("'","\"")
let queryUrl = sprintf "http://api.freebase.com/api/service/mqlread?query=%s" "{\"query\":"+query+"}"
let request : HttpWebRequest = downcast WebRequest.Create(queryUrl)
request.Method <- "GET"
request.ContentType <- "application/x-www-form-urlencoded"
let response = request.GetResponse()
let result =
try
use reader = new StreamReader(response.GetResponseStream())
reader.ReadToEnd();
finally
response.Close()
let data = Encoding.Unicode.GetBytes(result);
let stream = new MemoryStream()
stream.Write(data, 0, data.Length);
stream.Position <- 0L
stream
let test =
// get some JSON from the web
let stream = getJsonFromWeb()
// convert the stream of JSON into an F# Record
let JsonSerializer = Json.DataContractJsonSerializer(typeof<FreebaseResultRecord>)
let result: FreebaseResultRecord = downcast JsonSerializer.ReadObject(stream)
// save the Records to disk as JSON
use fs = new FileStream(@"C:\temp\freebase.json", FileMode.Create)
JsonSerializer.WriteObject(fs,result)
fs.Close()
// save the Records to disk as System Controlled XML
let xmlSerializer = DataContractSerializer(typeof<FreebaseResultRecord>);
use fs = new FileStream(@"C:\temp\freebase.xml", FileMode.Create)
xmlSerializer.WriteObject(fs,result)
fs.Close()
use fs = new FileStream(@"C:\temp\freebase-pretty.xml", FileMode.Create)
let xmlSerializer = XmlSerializer(typeof<FreebaseResultRecord>)
xmlSerializer.Serialize(fs,result)
fs.Close()
ignore(test)
答案 0 :(得分:4)
Blockquote我希望有一些快捷方式可以将无参数构造函数放到记录
上
这可以通过使用CLIMutable属性在F#3.0版中实现。将其添加到无参数构造函数和读/写属性(而不是只读属性)的记录类型中。
答案 1 :(得分:1)
为什么不使用DataContractSerializer(对于Xml)而不是XmlSerializer?这是数据合同的主要好处之一(多个预测的编程模型相同)。
(无法为F#记录创建无参数构造函数。)
答案 2 :(得分:1)
看起来您无法将记录更改为类 - 或者向其添加edfault构造函数。
提供的示例(基于本文:http://blogs.msdn.com/b/jomo_fisher/archive/2010/03/06/neat-sample-f-and-freebase.aspx)从api.freebase.com获取json流;然后我们反序列化为属性类;接下来将其序列化为Json到磁盘;然后将其序列化为Xml到磁盘(使用DataContract);最后,使用输出的最佳控件将其序列化为Xml到磁盘(使用XmlSerializer):
注意:
DataContract(系列)属性 DataContractJsonSerializer和 JSON.DataContractJsonSerializer - 这些都发生在类名和 memeber变量。 DataContract 东西很直接 - 而且 也适用于记录类型。
XmlSerializer(系列)属性 在班级和财产 的getter / setter。这需要类型 是一个默认的对象 构造函数和属性Getters和 具有与之关联的属性的Setter 他们每个人。如果财产没有 有一个吸气剂或者一个吸气剂 不会序列化 - 这是一个 惊讶(我想象默认 onstructor会确保 对象有违约价值 反序列化和制定者会 更新任何序列化的 - 但事实并非如此)。
另一个 nifty (叹气)的事情 XmlSerialization是那个类 不能包含在模块中。所以 我们将类型移动到命名空间......
namespace JSONExample
open System
open System.IO
open System.Net
open System.Text
open System.Web
open System.Xml
open System.Security.Authentication
open System.Runtime.Serialization //add assemnbly reference System.Runtime.Serialization System.Xml
open System.Xml.Serialization
open System.Collections.Generic
[<DataContract>]
type ChemicalElementRecord() =
[<field: DataMember(Name="name") >]
let mutable name: string = ""
[<field: DataMember(Name="boiling_point") >]
let mutable boilingPoint: string =""
[<field: DataMember(Name="atomic_mass") >]
let mutable atomicMass: string = ""
[<XmlAttribute("name")>]
member this.Name with get() = name and set v = name <- v
[<XmlAttribute("boiling-point")>]
member this.BoilingPoint with get() = boilingPoint and set v = boilingPoint <- v
[<XmlAttribute("atomic-mass")>]
member this.AtomicMass with get() = atomicMass and set v = atomicMass <- v
[<XmlRoot("freebase")>]
[<DataContract>]
type FreebaseResultRecord() =
[<field: DataMember(Name="code") >]
let mutable code: string = ""
[<field: DataMember(Name="result") >]
let mutable result: ChemicalElementRecord array = Array.empty
[<field: DataMember(Name="message") >]
let mutable message: string = ""
[<XmlElement("message")>]
member this.Message with get() : string = message and set v = message <- v
[<XmlArrayAttribute("chemical-elements")>]
[<XmlArrayItem(typeof<ChemicalElementRecord>, ElementName = "chemical-element")>]
member this.Result with get() = result and set v = result <- v
[<XmlAttribute("code")>]
member this.Code with get() = code and set v = code <- v
module Test =
let getJsonFromWeb() =
let query = "[{'type':'/chemistry/chemical_element','name':null,'boiling_point':null,'atomic_mass':null}]"
let query = query.Replace("'","\"")
let queryUrl = sprintf "http://api.freebase.com/api/service/mqlread?query=%s" "{\"query\":"+query+"}"
let request : HttpWebRequest = downcast WebRequest.Create(queryUrl)
request.Method <- "GET"
request.ContentType <- "application/x-www-form-urlencoded"
let response = request.GetResponse()
let result =
try
use reader = new StreamReader(response.GetResponseStream())
reader.ReadToEnd();
finally
response.Close()
let data = Encoding.Unicode.GetBytes(result);
let stream = new MemoryStream()
stream.Write(data, 0, data.Length);
stream.Position <- 0L
stream
let test =
// get some JSON from the web
let stream = getJsonFromWeb()
// convert the stream of JSON into an F# Record
let JsonSerializer = Json.DataContractJsonSerializer(typeof<FreebaseResultRecord>)
let result: FreebaseResultRecord = downcast JsonSerializer.ReadObject(stream)
// save the Records to disk as JSON
use fs = new FileStream(@"C:\temp\freebase.json", FileMode.Create)
JsonSerializer.WriteObject(fs,result)
fs.Close()
// save the Records to disk as System Controlled XML
let xmlSerializer = DataContractSerializer(typeof<FreebaseResultRecord>);
use fs = new FileStream(@"C:\temp\freebase.xml", FileMode.Create)
xmlSerializer.WriteObject(fs,result)
fs.Close()
use fs = new FileStream(@"C:\temp\freebase-pretty.xml", FileMode.Create)
let xmlSerializer = XmlSerializer(typeof<FreebaseResultRecord>)
xmlSerializer.Serialize(fs,result)
fs.Close()
ignore(test)