先前踩過幾次雷,今天才搞懂是怎麼回事。

PowerShell 內建的 ConvertFrom-JsonConvertTo-Json Cmdlet 可用來做 JSON 反序列化及序列化,串接 Pipeline 使用很方便,但有個問題 - 遇過好幾次狀況是在開發環境寫好 PowerShell 轉檔排程測試 OK,在線上環境運作時卻噴出 "ConvertFrom-Json : Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property." 錯誤。(經典「在我的電腦上明明可以」場景)

訊息很明確,是 JSON 太長導致,直覺反應是「實際的資料量比測試環境多」造成,雖然有些案例的測試資料量照理與實際環境相當,但當下沒多想,加上查到不少網友回報相似問題,便鄉愿地一口咬定是線上資料多了幾筆剛好越過門檻,設法改用 Json.NET 或是建立 System.Web.Script.Serialization.JavaScriptSerializer 並指定 MaxJsonLength了事。

今天想整理筆記確認 JSON 長度限制是多少以免將來再踩雷,卻發現一件可怕事實 - 依據文件 JavaScriptSerializer 預設 MaxJsonLength 約為 4MB,但我試做了 4MB、8MB 甚至 16MB 的 JSON ,都無法重現 JSON 超長無法 ConvertForm-Json 錯誤。這才想到,我的開發環境跟筆電都是 Windows 10,PowerShell 版本是 5.1,而問題線上環境是 Windows 2012R2,PowerShell 版本為 4.0,會不會是 5.1 版 ConvertFrom-Json 上限不同?

追查 Source Code,猜測獲得證實。

PowerShell 5.1 的 ConvertForm-Json 來自 C:\Windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.PowerShell.Commands.Utility\v4.0_3.0.0.0__31bf3856ad364e35\Microsoft.PowerShell.Commands.Utility.dll

反組譯追進原始碼,發現 PS 5.1 的 ConvertFrom-Json 默默把 JavaScriptSerializer.MaxJsonLength 提高到 2G 了!

先前多次發生「開發測試 OK,上線時爆炸」的狀況,這下有了合理解釋,不是線上資料量比測試資料多,而是 PS5.1 的上限比 PS4.0 高。牢記住這一點,未來使用 ConvertFrom-Json 時應能少踩一些踩雷,但應該規劃一下把線上環境的 PowerShell 升到 5.1 才是治本之道。

The issue of tested PowerShell script throwing the length of the string exceeds the value set on the maxJsonLength property exception in production environment.


Comments

# by Huang

常常會發生的,開發環境總是比線上環境的版本要新,一定要留意一下

Post a comment