首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

WP7 使用 JSON.NET 反序列化巢狀 JSON 失敗的排查與修正

     編輯:程式設計綜合問答

錯誤現象

反序列化以下 JSON 時報錯:

[
  {
    "class": "Board",
    "id": 1,
    "articles": [{"class": "Article", "id": 1}],
    "boardName": "122222",
    "boarder": {"class": "User", "id": 1},
    "description": "22222",
    "postCount": 0
  }
]

錯誤信息:Newtonsoft.Json.JsonConvert.DefaultSettings 未能計算表達式的值、emptyArray 相關字段不可用。

根本原因分析

  1. 類定義缺陷:List articles 缺少泛型參數,應為 List<Article> articles
  2. 循環引用:Board → Article → Board,User → Article → User 形成雙向循環,JSON.NET 預設會拋出 JsonSerializationException: Self referencing loop detected
  3. 字段名不匹配:JSON 中 boarder 對應 User 類,但 C# 類屬性名需一致或用 [JsonProperty] 標註
  4. WP7 環境限制:Silverlight 運行時部分反射受限,需確保類為 public、屬性有 public getter/setter

修正後的實體類

public class Board
{
    [JsonProperty("class")]
    public string Class { get; set; }
    
    public int Id { get; set; }
    
    [JsonProperty("articles")]
    public List<Article> Articles { get; set; }
    
    [JsonProperty("boardName")]
    public string BoardName { get; set; }
    
    [JsonProperty("boarder")]
    public User Boarder { get; set; }
    
    [JsonProperty("description")]
    public string Description { get; set; }
    
    [JsonProperty("postCount")]
    public int PostCount { get; set; }
}

public class Article
{
    [JsonProperty("class")]
    public string Class { get; set; }
    
    public int Id { get; set; }
    
    [JsonProperty("board")]
    public Board Board { get; set; }
    
    [JsonProperty("comments")]
    public List<Comment> Comments { get; set; }
    
    [JsonProperty("detail")]
    public string Detail { get; set; }
    
    [JsonProperty("lastReplyTime")]
    public string LastReplyTime { get; set; }
    
    [JsonProperty("owner")]
    public User Owner { get; set; }
    
    [JsonProperty("postTime")]
    public string PostTime { get; set; }
    
    [JsonProperty("replyCount")]
    public int ReplyCount { get; set; }
    
    [JsonProperty("title")]
    public string Title { get; set; }
}

public class User
{
    [JsonProperty("class")]
    public string Class { get; set; }
    
    public int Id { get; set; }
    
    [JsonProperty("address")]
    public string Address { get; set; }
    
    [JsonProperty("articles")]
    public List<Article> Articles { get; set; }
    
    // ... 其他屬性
}

public class Comment
{
    [JsonProperty("class")]
    public string Class { get; set; }
    
    public int Id { get; set; }
    
    [JsonProperty("article")]
    public Article Article { get; set; }
    
    [JsonProperty("detail")]
    public string Detail { get; set; }
    
    [JsonProperty("owner")]
    public User Owner { get; set; }
    
    [JsonProperty("postTime")]
    public string PostTime { get; set; }
}

解決循環引用的兩種方式

方式一:忽略循環引用(推薦)

var settings = new JsonSerializerSettings
{
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
    NullValueHandling = NullValueHandling.Ignore
};

List<Board> boards = JsonConvert.DeserializeObject<List<Board>>(json, settings);

方式二:使用 JsonObject/JsonArray 手動解析


JArray array = JArray.Parse(json);
foreach (JObject obj in array)
{
    string boardName = obj["boardName"].ToString();
    // 手動提取所需字段,避免實體類循環
}

WP7 專項注意事項

  • 引用 Newtonsoft.Json.Silverlight.dll 而非標準版
  • 確保項目目標框架為 Windows Phone 7.1 (7.1 SDK)
  • 異步下載 JSON 時用 WebClient.DownloadStringAsync + 回調
  • UI 線程更新用 Deployment.Current.Dispatcher.BeginInvoke

調試技巧

  1. 先用 JToken.Parse(json) 驗證 JSON 結構
  2. 逐個類測試:JsonConvert.DeserializeObject<Board>(singleBoardJson)
  3. 輸出序列化結果對比:JsonConvert.SerializeObject(board, Formatting.Indented)

總結

核心修正:補全泛型參數、加上 JsonProperty 屬性、配置 ReferenceLoopHandling.Ignore。WP7 環境下優先考慮手動 JToken 解析以規避反射限制。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved