指定DataContractJsonSerializer的输出格式?

时间:2017-08-17 11:39:00

标签: c# json serialization

对于手头的项目,我必须使用DataContractJsonSerializer进行序列化,并且必须根据成员的值生成特定的输出。

我的课看起来与此相似:

public class MyClass
{
  public string foo;
  public string bar;

  public MyClass(string f, string b = "")
  {
    this.foo = f;
    this.bar = b;
  }
}

现在序列化像

这样的列表
var list = new List<MyClass>
{
  new MyClass("foo", "bar"),
  new MyClass("foo1"),
  new MyClass("foo2", "bar2")
};

应该是这样的

[{"foo": "bar"}, "foo1", {"foo2": "bar2"}]

或 - 更好 - 转义并作为string

"[{\"foo\": \"bar\"}, \"foo1\", {\"foo2\": \"bar2\"}]"
  • 弦乐和物体的混合物。我怎么能实现这个目标?

我尝试覆盖ToString()方法并序列化相应的字符串,从而导致不必要的转义符号,例如bar2可能是m/s,并以m\\/s转义,无法在网络服务器上正确反序列化。

最后,我只需要序列化为这种格式。无需使用DataContractJsonSerializer反序列化此格式。

2 个答案:

答案 0 :(得分:1)

您要做的是有条件地将MyClass的实例替换为string List<MyClass>或字典,但是不支持使用原语作为代理项数据合同序列化,由Microsoft解释serialization surrogate

但是,由于您只需要序列化而不是反序列化,因此您可以通过手动将List<object>替换为代理MyClass来获取所需的输出,其中bar的实例被替换Dictionary<string, string>为空时带字符串,否则为DataContractJsonSerializer。然后在here中使用以下值手动construct true {/ 1}}:

(请注意,EmitTypeInformationUseSimpleDictionaryFormatMyType都是.NET 4.5的新手。)

因此,您可以按如下方式定义public interface IHasSerializationSurrogate { object ToSerializationSurrogate(); } public class MyClass : IHasSerializationSurrogate { public string foo; public string bar; // If you're not going to mark MyClass with data contract attributes, DataContractJsonSerializer // requires a default constructor. It can be private. MyClass() : this("", "") { } public MyClass(string f, string b = "") { this.foo = f; this.bar = b; } public object ToSerializationSurrogate() { if (string.IsNullOrEmpty(bar)) return foo; return new Dictionary<string, string> { { foo, bar } }; } }

public static partial class DataContractJsonSerializerHelper
{
    public static string SerializeJsonSurrogateCollection<T>(this IEnumerable<T> collection) where T : IHasSerializationSurrogate
    {
        if (collection == null)
            throw new ArgumentNullException();
        var surrogate = collection.Select(i => i == null ? null : i.ToSerializationSurrogate()).ToList();
        var settings = new DataContractJsonSerializerSettings
        {
            EmitTypeInformation = EmitTypeInformation.Never,
            KnownTypes = surrogate.Where(s => s != null).Select(s => s.GetType()).Distinct().ToList(),
            UseSimpleDictionaryFormat = true,
        };
        return DataContractJsonSerializerHelper.SerializeJson(surrogate, settings);
    }

    public static string SerializeJson<T>(this T obj, DataContractJsonSerializerSettings settings)
    {
        var type = obj == null ? typeof(T) : obj.GetType();
        var serializer = new DataContractJsonSerializer(type, settings);
        return SerializeJson<T>(obj, serializer);
    }

    public static string SerializeJson<T>(this T obj, DataContractJsonSerializer serializer = null)
    {
        serializer = serializer ?? new DataContractJsonSerializer(obj == null ? typeof(T) : obj.GetType());
        using (var memory = new MemoryStream())
        {
            serializer.WriteObject(memory, obj);
            memory.Seek(0, SeekOrigin.Begin);
            using (var reader = new StreamReader(memory))
            {
                return reader.ReadToEnd();
            }
        }
    }
}

然后介绍以下扩展方法:

var json = list.SerializeJsonSurrogateCollection();

并按如下方式将列表序列化为JSON:

[{"foo":"bar"},"foo1",null,{"foo2":"bar2"}]

具有以下结果:

DataContractJsonSerializer

如果你真的需要转义字符串(为什么?),你总是可以将结果字符串序列化为JSON 第二次var jsonOfJson = json.SerializeJson(); 产生双序列化结果:

"[{\"foo\":\"bar\"},\"foo1\",{\"foo2\":\"bar2\"}]"

导致

<?php

namespace myApp\AdminBundle\Entity;


use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;


/**
 * @ORM\Entity
 * @ORM\Table(name="fos_user")
 */
class User extends BaseUser
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    public function __construct()
    {
        parent::__construct();

    }
}
?>

答案 1 :(得分:0)

反序列化将根据名称和值组合进行,因此您的文本应该是这样的 [{“foo”:“foo”,“bar”:“bar”},{“foo”:“foo1”},{“foo”:“foo2”,“bar”:“bar2”}]