1

我有一个要序列化为字符串的复杂类型。我使用 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" }. 知道如何让它序列化为纯字符串,没有花括号吗?

4

2 回答 2

2

解决方案比预期的要容易。您可以JsonConverter使用GlobalConfiguration. 我做了一个抽象包装器JsonConverter,如下所示,其想法来自以下 SO 线程:如何在 JSON.NET 中实现自定义 JsonConverter 以反序列化基类对象列表?.

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);
    }
}

GlobalConfiguration然后最后在 Global.asax.cs 中注册一个实例

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new DateTimeToStringJsonConverter());

有什么想法/想法/意见吗?谢谢!


编辑:2018.10.16 - 更新代码以将值类型作为源类型处理并复制序列化程序设置,这要归功于原始SO 答案中的以下评论:

注意:这个解决方案遍布互联网,但有一个在极少数情况下会表现出来的缺陷。在 ReadJson 方法中创建的新 JsonReader 不会继承任何原始阅读器的配置值(Culture、DateParseHandling、DateTimeZoneHandling、FloatParseHandling 等)。在使用 serializer.Populate() 中的新 JsonReader 之前,应复制这些值。

于 2013-06-06T07:49:20.437 回答
1

导入这个命名空间 System.Web.Script.Serialization;

string SerializeObject()
{
     var objs = new List<Test>()
     var objSerialized = new JavaScriptSerializer();
     return objSerialized .Serialize(objs);
}

我以 List 为例,但您将使用您的对象。

于 2013-06-05T21:04:25.227 回答