如何将已引用索引的JSON数据反序列化为强类型C#对象?

时间:2012-10-09 00:26:29

标签: c# json json.net

我想反序列化JSON数据(使用Newtonsoft),类似于以下内容,并转换为C#中的强类型对象/列表,但无法弄清楚如何定义类,以便索引引用转换为引用对象。

{
  "Countries": [
    {
      "Name": "USA",

    },
    {
      "Name": "UK",
    },
    {
      "Name": "JAPAN",
    },
  ],
  "Authors": [
    {
      "DisplayName": "John Doe",
      "RealName": "Not John Doe"
    },
    {
      "DisplayName": "Jane Doe",
      "RealName": "Not Jane Doe"
    },
  ],
  "Books": [
    {
      "Author": 0,
      "Title": "A good read",
      "PublishedCountries": "0,1",

    },
    {
      "Author": 0,
      "Title": "Another good read",
      "PublishedCountries": "0,1",
    },
    {
      "Author": 1,
      "Title": "This one is even better",
      "PublishedCountries": "0,1,2",
    },
  ],
}

理想情况下,我想使用类似以下的类:

public class Country
{
  public string Name { get; set;}
}

public class AuthorDetails
{
  public string DisplayName { get; set; }
  public string RealName { get; set; }
}

public class Book
{
  public AuthorDetails Author { get; set; }
  public string Title { get; set; }
  public IEnumerable<Country> PublishedCountries { get; set; }
}

public class ListOfBooks
{
  public IEnumerable<Book> Books { get; set; }
}

并按照以下方式反序列化:

var listOfBooks = JsonConvert.DeserializeObject<ListOfBooks>(jsonAsString);

我不知道如何告诉Json.Net书JObject中的Author属性是一个索引,而不是一个整数。 PublishedCountries(以逗号分隔的索引列表)

也是如此

2 个答案:

答案 0 :(得分:1)

除了帮助反序列化过程之外,我看不到其他方法。

var dynObj = (JObject)JsonConvert.DeserializeObject(json);

var authors = dynObj["Authors"]
                .Select(j => new AuthorDetails { 
                            RealName = (string)j["RealName"], 
                            DisplayName = (string)j["DisplayName"] 
                })
                .ToList();

var countries = dynObj["Countries"]
                .Select(j => new Country { Name = (string)j["Name"]})
                .ToList();

var books = dynObj["Books"].Select(x => new Book
                {
                    Author = authors[(int)x["Author"]],
                    Title = (string)x["Title"],
                    PublishedCountries = x["PublishedCountries"].ToString().Split(',')
                                            .Select(i =>countries[int.Parse(i)])
                                            .ToList()
                })
                .ToList();

public class Country
{
    public string Name { get; set; }
}

public class AuthorDetails
{
    public string DisplayName { get; set; }
    public string RealName { get; set; }
}

public class Book
{
    public AuthorDetails Author { get; set; }
    public string Title { get; set; }
    public List<Country> PublishedCountries { get; set; }
}

答案 1 :(得分:0)

我相信你想要做的是'保留对象引用'。

您可以使用属性标记C#对象,以描述何时使用引用,而不是重复复制对象的内容:

[JsonObject(IsReference = true)](在类型声明中使用)

但是,您生成的Javascript看起来与您演示的内容不同,请看一下如何操作。

http://james.newtonking.com/projects/json/help/?topic=html/PreserveObjectReferences.htm

相反,您的JSON看起来更像是这样:

{
  "Countries": [
    {
      "Name": "USA",

    },
    {
      "Name": "UK",
    },
    {
      "Name": "JAPAN",
    },
  ],
  "Authors": [
    {
      "DisplayName": "John Doe",
      "RealName": "Not John Doe"
    },
    {
      "DisplayName": "Jane Doe",
      "RealName": "Not Jane Doe"
    },
  ],
  "Books": [
    {
      "$id": 1,
      "Author": 0,
      "Title": "A good read",
      "PublishedCountries": "0,1",

    },
    {
      "$ref": 1
    },
    {
      "Author": 1,
      "Title": "This one is even better",
      "PublishedCountries": "0,1,2",
    },
  ],
}