我在C#中有一个包含guid的结构.我正在使用DataContractJsonSerializer来序列化包含该类实例的对象.当我直接使用guid时,它被序列化为纯字符串,但现在它被序列化为名称/值对.这是一个NUnit测试和支持代码,用于演示此问题:
private static string ToJson<T>(T data)
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof (T));
using (MemoryStream ms = new MemoryStream())
{
serializer.WriteObject(ms, data);
return Encoding.Default.GetString(ms.ToArray());
}
}
[Serializable]
private class ID
{
private Guid _value;
public static explicit operator ID(Guid id)
{
return new ID { _value = id };
}
public static explicit operator Guid(ID id)
{
return id._value;
}
}
[Test]
public void IDShouldSerializeLikeGuid()
{
Guid guid = Guid.NewGuid();
ID id = (ID) guid;
Assert.That(ToJson(id), Is.EqualTo(ToJson(guid)));
}
Run Code Online (Sandbox Code Playgroud)
并且测试运行输出:
NUnit.Framework.AssertionException: …Run Code Online (Sandbox Code Playgroud) 我有以下代码:
[DataContract(Namespace = "")]
public class User
{
[DataMember]
public string UserName { get; set; }
[DataMember]
public string FullName { get; set; }
}
//Deserialization test
public void Test()
{
//CASE 1.
//string xml = "<User><UserName>john</UserName>" +
// "<FullName>John Lennon</FullName></User>";
//CASE 2.
string xml = "<User><FullName>John Lennon</FullName>" +
"<UserName>john</UserName></User>";
byte[] byteArray = Encoding.UTF8.GetBytes(xml);
User user = null;
using (MemoryStream stream = new MemoryStream(byteArray))
{
DataContractSerializer serializer =
new DataContractSerializer(typeof(User), "User", "");
user = (User)serializer.ReadObject(stream);
}
}
Run Code Online (Sandbox Code Playgroud)
在案例1中,FullName属性未反序列化,但在案例2中,它被正确反序列化.为什么?
如果我正在序列化并稍后反序列化类,DataContractSerializer我如何控制未序列化的属性的初始值?
考虑下面的Person课程.它的数据协定设置为序列化FirstName和LastName属性,但不是IsNew属性.我想IsNew初始化为TRUE是否将新Person实例化为新实例或从文件反序列化.
这很容易通过构造函数来完成,但据我所知,它DataContractSerializer不会调用构造函数,因为它们可能需要参数.
[DataContract(Name="Person")]
public class Person
{
[DataMember(Name="FirstName")]
public string FirstName { get; set; }
[DataMember(Name = "LastName")]
public string LastName { get; set; }
public bool IsNew { get; set; }
public Person(string first, string last)
{
this.FirstName = first;
this.LastName = last;
this.IsNew = true;
}
}
Run Code Online (Sandbox Code Playgroud) 我目前正在为我的DataSet使用包装类,以实现自定义序列化.我想使用DataContractSerializer(更像是必须使用它)但仍然支持自定义序列化.问题是,[DataContract]和[Serializable]属性似乎并没有很好地相处...我怎么能覆盖序列化,并支持BOTH DataContract和ISerializable序列化?包装器DataSet类的代码带到这里:
[Serializable()]
[System.Runtime.InteropServices.ComVisible(false)]
public class TestDatasetWrapper : TestDataSet, ISerializable
{
public TestDatasetWrapper()
: base()
{}
protected TestDatasetWrapper(SerializationInfo info, StreamingContext context)
{
SerializationHelper.DeserializeTypedDataSet(info, this);
}
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
SerializationHelper.AddTypedDataSetObjectData(info, this);
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢!
我对使用DataContractSerializer使用基元列表时设置自定义元素名称的最佳方法感兴趣.假设我有以下类,其中包含一个字符串列表作为DataMember.
[DataContract]
public class ClassName
{
[DataMember]
public List<String> FieldName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
默认情况下,此序列化为以下内容:
<ClassName xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<FieldName xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a:string>Value 1</a:string>
<a:string>Value 2</a:string>
<a:string>Value 3</a:string>
</FieldName>
</ClassName>
Run Code Online (Sandbox Code Playgroud)
我想让XML尽可能简单地通过XSLT进行转换,所以理想情况下我会将标签重命名为更有用的东西,比如Value.
一种可能的解决方案是创建一个扩展Collection的类,并为CollectionDataMember参数设置ItemName,我在这里找到它.我想知道是否有办法实现相同的目标,而不需要这个额外的类或其他形式的包装类.XML序列化程序使用XMLArray和XMLArrayItem参数来完成此操作,但DataContractSerializer似乎没有类似的功能.
感谢您的任何提示或想法!
c# wcf xml-serialization datacontract datacontractserializer
我有问题DataContractSerializer.我用它从ASP.NET Web Service返回的XML创建类实例.但实际上数据来源在这里并不重要.为了使整个案例更容易调试,我创建了一个简单的测试项目,只是序列化,问题仍然存在.
这是我的XML:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<GetTestURL p1:type="MyApp.GetTestUrlInfo" xmlns:p1="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices">
<TestURL>http://bing.com</TestURL>
<UserCount p1:type="Edm.Int32">1</UserCount>
<InitialCount p1:type="Edm.Int32">1</InitialCount>
<AverageExecutionTime p1:type="Edm.Int32">43</AverageExecutionTime>
</GetTestURL>
Run Code Online (Sandbox Code Playgroud)
我正在尝试将XML反序列化为:
[DataContract(Name = "GetTestURL", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")]
public class TestInfo
{
[DataMember(Name = "TestURL")]
public Uri TestUri { get; private set; }
[DataMember(Name = "UserCount")]
public int UserCount { get; private set; }
[DataMember(Name = "InitialCount")]
public int InitialCount { get; private set; }
[DataMember(Name = "AverageExecutionTime")]
public int AverageExecutionTime { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)
和我的序列化助手类:
public …Run Code Online (Sandbox Code Playgroud) 当我调用Web服务操作时,WCF使用DataContractSerializer将消息反序列化到代理类:为什么我不能这样做?
以下是ActLoginResponse.xml文件中的soap消息:
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:PlotiIntf" xmlns:ns2="urn:PlotiIntf-IPloti" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<s:Header xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"/>
<SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<ns2:ActLoginResponse>
<return>
<ResultCode>0</ResultCode>
<ResultMessage>Login et password correct.</ResultMessage>
<Acteur>
<Id>IMT_706</Id>
<Nom>IMA PROTECT</Nom>
<Prenom/>
<nbFI>0</nbFI>
<FonctionActeur>TS</FonctionActeur>
<Timeout>30</Timeout>
</Acteur>
<ZneGeoList xsi:nil="true"/>
</return>
</ns2:ActLoginResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Run Code Online (Sandbox Code Playgroud)
相应的ActLoginResponse类的WCF代理代码是:
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName="ActLoginResponse", WrapperNamespace="urn:PlotiIntf-IPloti", IsWrapped=true)]
public partial class ActLoginResponse {
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="", Order=0)]
public Ploti.PlotiClient.LoginResponseType @return;
public ActLoginResponse() {
}
public ActLoginResponse(Ploti.PlotiClient.LoginResponseType @return) {
this.@return = @return;
}
}
Run Code Online (Sandbox Code Playgroud)
所以我需要将XML解析为ActLoginResponse类型的对象实例.
以下是我执行解析的方法:
ActLoginResponse body;
FileStream stream = new FileStream("Requests\\ActLoginResponse.xml", FileMode.Open);
XmlReader xmlReader = XmlReader.Create(stream); …Run Code Online (Sandbox Code Playgroud) DataContractSerializer要求使用DataContract 和DataMember属性标记类和成员.但是,在我的情况下,使用EFPocoAdapater框架自动生成类,并且这些属性不存在.
如何在没有这些属性的情况下使用DataContractSerializer强制序列化所有成员?
来自Alexdej:
这改变了3.5SP1,希望你看到:http://www.pluralsight.com/community/blogs/aaron/archive/2008/05/13/50934.aspx
serialization entity-framework datacontractserializer efpocoadapter
我打算构建一个WCF服务,返回序列化为JSON的通用字典对象.不幸的是,序列化失败,因为对象可能总是不同.KnownTypes无法帮助,因为属性类型是Dictionary,我不能说KnownType,因为类可能总是不同.
如果有可能序列化"未知类型"的任何想法?
我不介意为每个类指定DataContract/DataMember,但(至少对于原型版本)我不希望每个响应都有强类型.Javascript客户端只是不在乎.
匿名课怎么样?
当反序列化用EnumMemberAttribute修饰的带有包含空格的值的标记枚举时,将抛出SerializationException.值中的空格被视为分隔符.
有没有办法更改分隔符或将值放在引号中?或者是否有更简单的解决方案?
我正在考虑的选项是:
但我真的觉得这应该是可配置的东西或其他人已经解决的东西.但我找不到任何东西.
我把问题归结为一个简单的单元测试.以下代码导致:
消息=无效的枚举值' Test '无法反序列化为'UnitTests.TestEnum'类型.确保存在必要的枚举值,并且如果类型具有DataContractAttribute属性,则使用EnumMemberAttribute属性标记.来源= System.Runtime.Serialization
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnitTests
{
[TestClass]
public class EnumSerizalizationTests
{
[TestMethod]
public void SerializingAndDesrializingAFlaggedEnumShouldResultInSameEnumValues()
{
//Arrange
var orgObject = new TestClass { Value = TestEnum.TestValue1 | TestEnum.TestValue2 };
//Act
var temp = DataContractSerializeObject(orgObject);
var newObject = DataContractDeSerializeObject<TestClass>(temp);
//Assert
newObject.ShouldBeEquivalentTo(orgObject, "Roundtripping serialization should result in same value");
}
public string DataContractSerializeObject<T>(T objectToSerialize)
{
using (var output = new StringWriter()) …Run Code Online (Sandbox Code Playgroud)