对于手头的项目,我必须使用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
反序列化此格式。
答案 0 :(得分:1)
您要做的是有条件地将MyClass
的实例替换为string
List<MyClass>
或字典,但是不支持使用原语作为代理项数据合同序列化,由Microsoft解释serialization surrogate。
但是,由于您只需要序列化而不是反序列化,因此您可以通过手动将List<object>
替换为代理MyClass
来获取所需的输出,其中bar
的实例被替换Dictionary<string, string>
为空时带字符串,否则为DataContractJsonSerializer
。然后在here中使用以下值手动construct true
{/ 1}}:
将DataContractJsonSerializerSettings
设置为代理对象列表中实际类型的列表。
将KnownTypes
设为EmitTypeInformation
。这会抑制在输出JSON中包含EmitTypeInformation.Never
。
将type hints设为DataContractJsonSerializerSettings
。
(请注意,EmitTypeInformation
,UseSimpleDictionaryFormat
和MyType
都是.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”}]