Подтвердить что ты не робот

Как добавить пользовательский root node при сериализации объекта с помощью JSON.NET?

Я добавил свойство custom для некоторых из моих объектов:

[JsonCustomRoot("status")]
public class StatusDTO 
{
    public int StatusId { get; set; }
    public string Name { get; set; }
    public DateTime Created { get; set; }
}

Атрибут очень прост:

public class JsonCustomRoot :Attribute
{
    public string rootName { get; set; }

    public JsonCustomRoot(string rootName)
    {
        this.rootName = rootName;
    }
}

Вывод по умолчанию из JSON.NET при сериализации экземпляра объекта:

{"StatusId":70,"Name":"Closed","Created":"2012-12-12T11:50:56.6207193Z"}

Теперь возникает вопрос: Как добавить root-node в JSON со значением настраиваемого атрибута, например::

{status:{"StatusId":70,"Name":"Closed","Created":"2012-12-12T11:50:56.6207193Z"}}

Я нашел несколько статей, в которых упоминается интерфейс IContractResolver, но я не могу понять, как это сделать. Мои попытки включают этот незавершенный фрагмент кода:

protected override JsonObjectContract CreateObjectContract(Type objectType)
{
    JsonObjectContract contract = base.CreateObjectContract(objectType);

    var info = objectType.GetCustomAttributes()
                   .SingleOrDefault(t => (Type)t.TypeId==typeof(JsonCustomRoot));
    if (info != null)
    {
        var myAttribute = (JsonCustomRoot)info;
        // How can i add myAttribute.rootName to the root from here?
        // Maybe some other method should be overrided instead?
    }

    return contract;
}
4b9b3361

Ответ 1

Вот решение специально для Web API, которое я также использую: RootFormatter.cs

Я написал его на основе Создание форматирования JSONP для веб-API ASP.NET.

Вместо использования настраиваемого атрибута я повторно использую поле заголовка JsonObjectAttribute. Здесь используется код использования:

using Newtonsoft.Json

[JsonObject(Title = "user")]
public class User
{
    public string mail { get; set; }
}

Затем добавьте RootFormatter в свой App_Start и зарегистрируйте его следующим образом в WebApiConfig:

GlobalConfiguration.Configuration.Formatters.Insert(0, new RootFormatter());

Мне удалось получить завернутый ответ, подобный WCF WebMessageBodyStyle.Wrapped:

{"user":{
  "mail": "[email protected]ample.com"
}}

Ответ 2

Что делать, если вы используете анонимный объект?

JSON.Serialize(new { status = targetObject});

Ответ 3

Очень простой способ приблизиться к этому - разместить объект внутри другого объекта. возможно, более упрощенно было смотреть на него, но это работает при работе с коллекциями и особыми объектами.

  public class StatusDTO
    {
        public int StatusId { get; set; }
        public string Name { get; set; }
        public DateTime Created { get; set; }
    }

    public class statusJasonModel
    {
        public StatusDTO status { get; set; }
    }

Теперь, если вы поместите StatusDTO внутри объекта statusJsonModel и сериализуете его как Json. Он должен дать вам желаемый ответ.

Ответ 4

У меня была аналогичная задача в одном из моих проектов. Ниже приведен шаг, который я принял для решения проблемы.

1. Класс My Entity

public class Product
    {
        [Key]
        public string Id { get; set; }
        public string Title { get; set; }
        public string Album { get; set; }
        public string Artist { get; set; }
        public string Genre { get; set; }

    }

2. Создал другой класс, который определен в этой форме.

    public class KindOfMedia
        {
            public KindOfMedia()
            {
                Product = new List<Product>();
            }
            public List<Product> Product { get; set; }
        }

3. Контроллер Web API, который вернет json

            public HttpResponseMessage Products()
            {
                var kind = new KindOfMedia();
                kind.Products = new List<Product>();
                kind.Products.Add(new Product
                {
                    Id = Guid.NewGuid().ToString(),
                    Title = "I am A Winner",
                    Album = "",
                    Artist = "Project Fame",
                    Genre = "Contemporal"                
                });
                kind.Products.Add(new Product
                {
                    Id = Guid.NewGuid().ToString(),
                    Title = "Great Nation",
                    Album = "Oceans",
                    Artist = "Timi Dakolo",
                    Genre = "Gospel"
                });

                return Request.CreateResponse(HttpStatusCode.OK, kind);
            }

4. Добавьте эту строку кода в файл конфигурации WebApi в папке App_Start

     var json = config.Formatters.JsonFormatter;
                json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.None;

обратите внимание, что Newtonsoft.Json.PreserveReferencesHandling.None не сохранит ссылку типа сериализации

Полученный Json

{
  "Musics": [
    {
      "Id": "bf9faeee-7c39-4c33-a0ea-f60333604061",
      "Title": "I am A Winner",
      "Album": "",
      "Artist": "Project Fame",
      "Genre": "Contemporal"
    },
    {
      "Id": "243edd32-7ba2-4ac4-8ab9-bba6399cb0a6",
      "Title": "Great Nation",
      "Album": "Oceans",
      "Artist": "Timi Dakolo",
      "Genre": "Gospel"
    }
  ]
}