【发布时间】:2016-09-01 11:00:20
【问题描述】:
我有以下控制台应用程序:
using System;
using System.IO;
using System.Xml.Serialization;
using Newtonsoft.Json;
namespace OutputApp
{
public class Foo
{
public object Value1 { get; set; }
public string Value2 { get; set; }
}
public class Bar
{
public int Arg1 { get; set; }
public double Arg2 { get; set; }
}
class Program
{
public static Foo CreateFooBar()
{
return new Foo
{
Value1 = new Bar
{
Arg1 = 123,
Arg2 = 99.9
},
Value2 = "Test"
};
}
public static string SerializeXml(object obj)
{
using (var stream = new MemoryStream())
{
using (var reader = new StreamReader(stream))
{
var serializer = new XmlSerializer(obj.GetType());
serializer.Serialize(stream, obj);
stream.Position = 0;
return reader.ReadToEnd();
}
}
}
static void Main(string[] args)
{
var fooBar = CreateFooBar();
// Using Newtonsoft.Json
var json = JsonConvert.SerializeObject(fooBar, Formatting.Indented);
var xnode = JsonConvert.DeserializeXNode(json, "RootElement");
var xml = xnode.ToString();
// Using XmlSerializer, throws InvalidOperationException
var badXml = SerializeXml(fooBar);
Console.ReadLine();
}
}
}
我有两节课。 Foo 类和 Bar 类。 Foo 类具有 object 类型的属性。这是一个要求,因为它是一个可以保存各种对象的合同,因此我不能将属性设置为具体类型或泛型。
现在我使用CreateFooBar() 方法组成一个虚拟的fooBar 对象。之后,我首先将它序列化为 JSON,它与 Json.Net 完美结合。
然后我使用 Json.Net 的 XML 转换器方法将 json 字符串转换为 XNode 对象。它也很好用。
两者的输出如下:
{
"Value1": {
"Arg1": 123,
"Arg2": 99.9
},
"Value2": "Test"
}
<RootElement>
<Value1>
<Arg1>123</Arg1>
<Arg2>99.9</Arg2>
</Value1>
<Value2>Test</Value2>
</RootElement>
虽然这可行,但肯定不是很好,因为我必须序列化为 json,然后才能将其序列化为 xml。我想直接序列化成xml。
当我使用 XmlSerializer 执行此操作时,我得到了臭名昭著的 InvalidOperationExceptoin,因为我没有使用 XmlInclude 属性装饰我的类或使用 other workarounds 之一。
无效操作异常
OutputApp.Bar 类型不是预期的。使用 XmlInclude 或 SoapInclude 属性指定静态未知的类型。
XmlSerializer 的任何变通方法都不是一个好的解决方案恕我直言,我认为不需要它,因为在没有 crappy 属性的情况下将对象序列化为 XML 是完全可行的。
有没有人知道 .NET 中有一个好的 Xml 序列化程序可以做到这一点,或者是否有计划将此功能添加到 Json.Net?
有什么想法吗?
更新1
我不反对使用属性,但它需要有意义。我不喜欢XmlInclude 属性的地方是它迫使我陷入循环依赖。假设我有定义基类的程序集 A 和实现派生类的程序集 B。现在 XmlInclude 属性的工作方式是,我必须使用程序集 B 中的子类的类型名称来装饰程序集 A 中的基类。这意味着我有一个循环依赖并且不可行!
更新2
我要澄清的是,我不是在寻找一种解决方案来重构我的控制台应用程序以使其与XmlSerializer 一起工作,我正在寻找一种对我拥有的内容进行 XML 序列化的方法。
下面有一条评论提到使用object 作为数据类型是糟糕的设计。不管这是否属实,这完全是另一回事。关键是它没有理由不能序列化为 XML,我很想找到这样的解决方案。
我个人认为创建“标记”界面是一种肮脏的设计。它滥用接口来解决单个 .NET 类 (XmlSerializer) 的缺陷。如果我将序列化库换成其他东西,那么整个标记界面将是多余的混乱。我不想将我的类耦合到一个序列化程序。
我正在寻找一个优雅的解决方案(如果有的话)?
【问题讨论】:
-
既然你反对“蹩脚的属性”,听起来你的思想可能是封闭的。您是否仍然愿意尝试任何解决方案,即使在您看来并不完美?
-
当然,但它必须有意义。我不喜欢属性的是它迫使我陷入循环依赖。假设我有定义基类的程序集 A 和实现派生类的程序集 B。现在 XmlInclude 属性的工作方式是我必须使用程序集 B 中的子类的类型名称来装饰程序集 A 中的基类。繁荣,循环依赖。这是不行的!
-
如果您使用的是 XmlSerializer,那么任何类型的循环依赖都应该没有问题。再简单不过了:)
标签: c# json xml serialization json.net