2015-05-20 3 views
4

До сих пор я использовал DataContractJsonSerializer Microsoft для сериализации и десериализации моих бизнес-объектов в объекты передачи данных (DTO), отформатированные как JSON. DTO отмечены атрибутом DataContract. Небольшой пример:(De-) Сериализовать известные типы, похожие на Microsoft

[DataContract(Name = "Geometry", Namespace = "myContract.com/dto")] 
[KnownType(typeof(Point))] 
[KnownType(typeof(Line))] 
public class Geometry 
{ 
} 

[DataContract(Name = "Point", Namespace = "myContract.com/dto")] 
public class Point : Geometry 
{ 
    [DataMember(Name = "x")] 
    public double X { get; set; } 

    [DataMember(Name = "y")] 
    public double Y { get; set; } 
} 

[DataContract(Name = "Line", Namespace = "myContract.com/dto")] 
public class Line: Geometry 
{ 
    [DataMember(Name = "start")] 
    public Point Start { get; set; } 

    [DataMember(Name = "end")] 
    public Point End { get; set; } 
} 

Это получает сериализовать как:

"geometry":{"__type":"Point:myContract.com/dto","x":23133.75569999963,"y":21582.385849999264} 

Из-за проблем с производительностью я перешел на Newtonsoft Json.NET. При использовании этого строки JSON выглядит следующим образом:

"geometry":{"$type":"A.B.C.Point, A.B.C","x":23133.75569999963,"y":21582.385849999264} 

Есть Есть возможность сериализации объекта с Json.NET в строку Microsoft-соответствие JSON с помощью «__type» и контракт имен вместо «$ типа "и комбинация классов-сборок? Я использую .NET 3.5.

Заранее благодарен!

ответ

0

К сожалению, это не представляется возможным регулировать имя свойства, поскольку он объявлен в внутреннейJsonTypeReflector.cs class как:

public const string TypePropertyName = "$type"; 

Примечание: с другой стороны, значение свойство тип может быть изменен , SerializationBinder Class предназначен для этой цели, this example демонстрирует, как указать значение свойства настраиваемого типа.


Я хотел бы предложить следующее решение, которое позволяет писать пользовательский тип свойства. Во-первых, нам необходимо ввести базовый класс сущностей (или изменить Geometry класс) с типом недвижимости, как показано ниже

[DataContract(Name = "Entity", Namespace = "myContract.com/dto")] 
public abstract class Entity 
{ 
    [DataMember(Name = "__type", Order = 0)] 
    public string EntityTypeName 
    { 

     get 
     { 
      var typeName = GetType().Name; 
      if (Attribute.IsDefined(GetType(), typeof(DataContractAttribute))) 
      { 
       var attribute = GetType().GetCustomAttributes(typeof(DataContractAttribute), true).FirstOrDefault() as DataContractAttribute; 
       if (attribute != null) typeName = typeName + ":" + attribute.Namespace; 
      } 
      return typeName; 
     } 
    } 
} 

Затем измените Geometry класс:

[DataContract(Name = "Geometry", Namespace = "myContract.com/dto")] 
[KnownType(typeof(Point))] 
[KnownType(typeof(Line))] 
public class Geometry : Entity 
{ 
} 

И последний шаг, установить JsonSerializerSettings.TypeNameHandling в TypeNameHandling.None в закажите десериализатор, чтобы пропустить рендеринг атрибута $type.

Пример

var point = new Point { X = 23133.75569999963, Y = 21582.385849999264 }; 

    var jsonPoint = JsonConvert.SerializeObject(point, new JsonSerializerSettings 
    { 
     TypeNameHandling = TypeNameHandling.None, //do not write type property(!) 
    }); 
    Console.WriteLine(jsonPoint); 

Результат

{\"__type\":\"Point:myContract.com/dto\",\"x\":23133.75569999963,\"y\":21582.385849999264} 

P.S.

Вы также можете указать порядок, используя DataMember.Order, как показано ниже:

[DataContract(Name = "Point", Namespace = "myContract.com/dto")] 
public class Point : Geometry 
{ 
    [DataMember(Name = "x",Order = 1)] 
    public double X { get; set; } 

    [DataMember(Name = "y", Order = 2)] 
    public double Y { get; set; } 
} 

[DataContract(Name = "Line", Namespace = "myContract.com/dto")] 
public class Line : Geometry 
{ 
    [DataMember(Name = "start", Order = 1)] 
    public Point Start { get; set; } 

    [DataMember(Name = "end", Order = 2)] 
    public Point End { get; set; } 
} 
+0

Спасибо за ваше предложение! Это означало бы, что все мои DTO, наследующие от Entity, будут иметь известный тип.Напротив, Microsoft Serializer устанавливает это свойство только в случае необходимости. Вы видите какой-либо шанс справиться с этим автоматически? – mu88