在ASP.Net MVC中将JSON转换为C#类

时间:2013-10-31 13:27:10

标签: c# asp.net-mvc json asp.net-mvc-3

我正在尝试编写API - 其网站上显示的预期输出(针对第三方)是下面的JSON:

{
"api_version" : 4 ,
"hotel_ids" : [97497],   
"hotels" :
    [
        {
            "hotel_id": 97497,
            "room_types":
                {
                    "Fenway Room":
                        {
                            "url": "someurlhere",
                            "price": 178.50, 
                            "room_code": "SINGLE"                               
                        }
                }
        }
    ]
}

我正在使用在线工具:http://json2csharp.com/

它给了我以下课程:

public class FenwayRoom
{
public string url { get; set; }
public double price { get; set; }
public string room_code { get; set; }
}

public class RoomTypes
{
public FenwayRoom __invalid_name__Fenway Room { get; set; }
}

public class Hotel
{
public int hotel_id { get; set; }
public RoomTypes room_types { get; set; }
}

public class RootObject
{
public int api_version { get; set; }
public List<int> hotel_ids { get; set; }
public List<Hotel> hotels { get; set; }
}

您可以在RoomTypes中看到:

FenwayRoom __invalid_name__Fenway Room { get; set; }

我想知道他们对JSON的规范是否错误,或者我是否有办法创建类来返回他们期望的JSON?

在这个例子中,我认为房间类型“Fenway Room”是一个变量 - 所以我不认为它也可以是一个类名。但可能只是因为我不知道如何创建这样的类。

我只是无法弄清楚“芬威室” - 我认为它需要有类似的东西:“房间名称”:“芬威室” - 但也许还有另一种定义类的方法,以便它不会需要一个标签“房间名称”。

我非常感谢您确认是否可以创建与JSON相匹配的类。

谢谢,Mark

4 个答案:

答案 0 :(得分:1)

将您的课程改为以下结构:

public class Rootobject
{
    public int api_version { get; set; }
    public List<int> hotel_ids { get; set; }
    public List<Hotel> hotels { get; set; }
}

public class Hotel
{
    public int hotel_id { get; set; }
    public Room_Types room_types { get; set; }
}

public class Room_Types
{
    public List<Room> Rooms { get; set; }
}

public class Room
{
    public string Type { get; set; }
    public string Url { get; set; }
    public float Price { get; set; }
}

创建以下类,该类实现JsonConverter抽象类:

public abstract class MyJsonConverter<T> : JsonConverter
{
    protected abstract T Create(Type objectType, JObject jObject);

    public override bool CanConvert(Type objectType)
    {
        return typeof(T).IsAssignableFrom(objectType);
    }

    public override object ReadJson
        (JsonReader reader, 
        Type objectType,
        object existingValue,
        JsonSerializer serializer)
    {
        JObject jObject = JObject.Load(reader);
        T target = Create(objectType, jObject);
        serializer.Populate(jObject.CreateReader(), target);
        return target;
    }

    public override void WriteJson
        (JsonWriter writer, 
        object value, 
        JsonSerializer serializer)
    {
        //
    }
}

按如下方式实施MyJsonConverter<T>课程:

public class RoomConverter : MyJsonConverter<Room_Types>
{
    protected override Room_Types Create(Type objectType, JObject jObject)
    {
        var rooms = jObject.Cast<JToken>().Select(t => new Room
        {
            Type = ((JProperty)t).Name,
            Url = ((JProperty)t).First
                .SelectToken("url").ToString(),
            Price = float.Parse(((JProperty)t).First
                .SelectToken("price").ToString())
        }).ToList();
        return new Room_Types() { Rooms = rooms };
    }
    public override void WriteJson
        (JsonWriter writer, 
        object value, 
        JsonSerializer serializer)
    {
        writer.WriteStartObject();
        ((Room_Types)value).Rooms.ForEach(r =>
        {
            writer.WritePropertyName(r.Type);
            writer.WriteStartObject();
            writer.WritePropertyName("url");
            writer.WriteValue(r.Url);
            writer.WritePropertyName("price");
            writer.WriteValue(r.Price);
            writer.WriteEndObject();
        });
        writer.WriteEndObject();
    }
}

现在您可以像这样反序列化/序列化:

var result = JsonConvert
    .DeserializeObject<Rootobject>(jsonText, new RoomConverter());
var serialized = JsonConvert
    .SerializeObject(result, new RoomConverter());

答案 1 :(得分:1)

使用Json.NET时的输出

"room_types":
{
    "Fenway Room":
    {
        "url": "someurlhere",
        "price": 178.50, 
        "room_code": "SINGLE"                               
        }
    }
}

准确地查看序列化词典的内容。

将班级更改为

public class Room
{
    public string url { get; set; }
    public double price { get; set; }
    public string room_code { get; set; }
}

public class Hotel
{
    public int hotel_id { get; set; }
    public Dictionary<string, Room> room_types { get; set; }
}

public class RootObject
{
    public int api_version { get; set; }
    public List<int> hotel_ids { get; set; }
    public List<Hotel> hotels { get; set; }
}

这完全取决于使用Json.NET,它以免费方式为您提供此格式的字典序列化/反序列化。您可以使用.NET框架序列化程序执行此操作,但您需要执行额外的工作。

答案 2 :(得分:0)

尝试添加JsonPropteryAttribute。

public class RoomTypes
{
    [JsonProperty(PropertyName="FenWay Room")]
    public FenwayRoom room { get; set; }
}

答案 3 :(得分:0)

如果您使用此工具(http://jsonclassgenerator.codeplex.com/),它将生成稍微好一些支持这些属性名称的C#。

//由Xamasoft JSON类生成器生成 // http://www.xamasoft.com/json-class-generator

使用System; 使用System.Collections.Generic; 使用Newtonsoft.Json; 使用Newtonsoft.Json.Linq; 使用Example.SampleResponse1JsonTypes;

namespace Example.SampleResponse1JsonTypes
{

    internal class FenwayRoom
    {

        [JsonProperty("url")]
        public string Url { get; set; }

        [JsonProperty("price")]
        public double Price { get; set; }

        [JsonProperty("room_code")]
        public string RoomCode { get; set; }
    }

    internal class RoomTypes
    {

        [JsonProperty("Fenway Room")]
        public FenwayRoom FenwayRoom { get; set; }
    }

    internal class Hotel
    {

        [JsonProperty("hotel_id")]
        public int HotelId { get; set; }

        [JsonProperty("room_types")]
        public RoomTypes RoomTypes { get; set; }
    }

}

namespace Example
{

    internal class SampleResponse1
    {

        [JsonProperty("api_version")]
        public int ApiVersion { get; set; }

        [JsonProperty("hotel_ids")]
        public int[] HotelIds { get; set; }

        [JsonProperty("hotels")]
        public Hotel[] Hotels { get; set; }
    }

}