我有一个复杂的类型,要序列化为字符串。我使用IXmlSerializable按需工作,现在我也尝试让它适用于JSON消息。目前我通过DataContractSerializer将其序列化为以下内容:
<MyXmlRootElement>_value's contents</MyXmlRootElement>
对于JSON输出,我想收到一个带有_value内容的JSON字符串。
此类型实现的内容多于下面描述的内容,还通过挂钩到我们的Web服务框架中的一些其他属性来影响生成的wsdl。所以生成的wsdl / xsd看起来都很棒,它只是没有给我所需的JSON。
[XmlRoot(ElementName = "MyXmlRootElement", Namespace = "MyNamespace"]
public class ComplexType : IXmlSerializable
{
private string _value;
public ComplexType(string value) { _value = value; }
#region IXmlSerialiable Implementation
public XmlSchema GetSchema() { return null; }
public void ReadXml(XmlReader reader)
{
_value = reader.ReadString();
}
public void WriteXml(XmlWriter writer)
{
writer.WriteString(_value);
}
#endregion
}
我尝试实现ISerializable,这确实会影响生成的JSON,但它仍然将它放在一个复杂的(对象)类型中,即{ "ValueKey": "_value's contents" }
。知道如何将它序列化为纯字符串,没有花括号吗?
答案 0 :(得分:2)
解决方案比预期的要容易。您可以使用JsonConverter
注册GlobalConfiguration
。我在JsonConverter
周围做了一个抽象包装,如下所示,其思路来自以下SO线程:How to implement custom JsonConverter in JSON.NET to deserialize a List of base class objects?。
public abstract class CustomJsonConverter<T, TResult> : JsonConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// Load token from stream
var token = JToken.Load(reader);
// Create target object based on token
var target = Create(objectType, token);
var targetType = target.GetType();
if (targetType.IsClass && targetType != typeof(string))
{
// Populate the object properties
var tokenReader = token.CreateReader();
CopySerializerSettings(serializer, tokenReader);
serializer.Populate(token.CreateReader(), target);
}
return target;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
T typedValued = (T)value;
TResult valueToSerialize = Convert(typedValued);
serializer.Serialize(writer, valueToSerialize);
}
public override bool CanConvert(Type objectType)
{
return typeof (T) == objectType;
}
protected virtual T Create(Type type, JObject jObject)
{
// reads the token as an object type
if (typeof(TResult).IsClass && typeof(T) != typeof(string))
{
return Convert(token.ToObject<TResult>());
}
var simpleValue = jObject.Value<TResult>();
return Convert(simpleValue);
}
protected abstract TResult Convert(T value);
protected abstract T Convert(TResult value);
private static void CopySerializerSettings(JsonSerializer serializer, JsonReader reader)
{
reader.Culture = serializer.Culture;
reader.DateFormatString = serializer.DateFormatString;
reader.DateTimeZoneHandling = serializer.DateTimeZoneHandling;
reader.DateParseHandling = serializer.DateParseHandling;
reader.FloatParseHandling = serializer.FloatParseHandling;
}
}
然后,您可以使用此功能执行以下操作
public class DateTimeToStringJsonConverter : CustomJsonConverter<DateTime, string>
{
protected override string Convert(DateTime value)
{
return value.ToString();
}
protected override DateTime Convert(string value)
{
return DateTime.Parse(value);
}
}
然后最后在Global.asax.cs
中注册GlobalConfiguration
的实例
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new DateTimeToStringJsonConverter());
任何想法/想法/意见?谢谢!
编辑:2018.10.16 - 由于来自原始SO answer的以下评论,更新了处理值类型作为源类型并复制序列化设置的代码:
注意:此解决方案遍布互联网,但有一个缺陷,在极少数情况下会出现。在ReadJson方法中创建的新JsonReader不会继承任何原始读者的配置值(Culture,DateParseHandling,DateTimeZoneHandling,FloatParseHandling等等)。在serializer.Populate()中使用新的JsonReader之前,应复制这些值。
答案 1 :(得分:1)
导入此命名空间System.Web.Script.Serialization;
string SerializeObject()
{
var objs = new List<Test>()
var objSerialized = new JavaScriptSerializer();
return objSerialized .Serialize(objs);
}
我使用List作为示例,但您将使用您的对象。