5

我正在尝试编写一个 API - 他们网站上显示的预期输出(对于第 3 方)是下面的 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”是一个变量——所以我不认为它也可以是一个类名。但可能只是我不知道如何创建这样的类。

我只是无法弄清楚“Fenway Room” - 我认为它需要有类似:“Room Name”:“Fenway Room” - 但也许还有另一种定义类的方法,因此它不需要标签“房间名称”。

在确认是否可以创建类以匹配其 JSON 时,我将不胜感激。

谢谢,马克

4

4 回答 4

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());
于 2013-10-31T15:47:16.047 回答
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 框架序列化程序执行此操作,但您需要做额外的工作。

于 2013-10-31T15:54:03.897 回答
0

尝试添加 JsonPropteryAttribute。

public class RoomTypes
{
    [JsonProperty(PropertyName="FenWay Room")]
    public FenwayRoom room { get; set; }
}
于 2013-10-31T13:35:00.620 回答
0

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

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

使用系统;使用 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; }
    }

}
于 2013-10-31T13:45:11.630 回答