主頁 > .NET開發 > 將C#Dictionary<string,string>傳遞到TypeScriptMap<string,string>

將C#Dictionary<string,string>傳遞到TypeScriptMap<string,string>

2021-12-31 17:11:14 .NET開發

當 c# 后端回傳一個字典物件時,我試圖找到一種處理 TypeScript 中鍵:值對的最佳方法,但我嘗試過的任何方法都沒有按預期作業。

這是我的 C# 代碼:

    var displayFileds = new Dictionary<string, string>();
    displayFileds.Add("A", "A Value");
    displayFileds.Add("B", "B Value");

這是打字稿

type MyResponse = {
  displayFields: Map<string,string>
}

console.log(response.displayFields)

//sample of Map created in Typescript directly
let map = new Map([
  ["A", "A value"],
  ["B", "B value"]
]);

console.log(map)

我希望看到 console.log 的值相同,但它們完全不同,但為什么呢?如果無法將物件直接反序列化為 Map,那么在 TypeScript 中處理 Dictionaries 的最佳方法是什么?

將 C# Dictionary<string,string> 傳遞到 TypeScript Map<string,string>

[ 編輯 ]

這是從后端獲取日期的方式(我正在使用 Axios):

const { data } = await secureAxios.post<MyResponse> 
(ApiEndpoints.GetResponse, request)

和回應型別:

export type MyResponse= {
  displayFields: Map<string,string>
}

正如您從上面的 devtools 輸出中看到的那樣,我沒有像型別建議的那樣取回 Map<string,string> 而是只是一個物件,這不是我想要的

uj5u.com熱心網友回復:

  • 你的打字稿type MyResponse是錯誤的
    • 默認情況下,兩者Newtonsoft.Json(又名 JSON.NET)和System.Text.Json將序列化為Dictionary<String,String>具有字串鍵和字串值的 JSON 物件。

      • IE interface MyResponse { readonly [key: string]: string }
    • JSON只能包含物件常量(即JavaScript的一些組合物objectArray值(使用表達{}[]分別地),和其他原始文本(嚴格限于string文字,number文本,和true/ false/ null

      • 即您不能呼叫 JavaScript 類建構式 - 也不能使用任何需要構造物件的物件/型別,因此Map在 JSON 中參考該型別是非法的。
    • 但是您的 TypeScripttype MyResponse使用了該Map物件,如上所述,物件不正確/錯誤/非法。


可能的解決方案:

  • 如果字典鍵集是“靜態的”并且構成您的 Web 服務“合同”的一部分,那么您應該使用定義良好的 C# DTOclass并讓您的 JSON 序列化程式為您處理它。

    • 比擁有任意和未記錄的 JSON 物件鍵要好得多,意味著您可以使用代碼生成工具為任何平臺(Web、TypeScript、Java、Rust,甚至COBOL自動創建 Web 服務客戶端庫

      MyResponse.cs

      public class MyResponse
      {
          [JsonConstructor]
          public MyResponse(
              [JsonProperty("displayFields")] MyResponseFields displayFields
          )
          {
              this.DisplayFields = displayFields ?? throw new ArgumentNullException(nameof(displayFields));
          }
      
          [JsonProperty("displayFields")]
          public MyResponseFields DisplayFields { get; }
      }
      
      public class MyResponseFields
      {
          [JsonConstructor]
          public MyResponseFields(
              [JsonProperty("a")] String a,
              [JsonProperty("b")] String b
          )
          {
              this.A = a;
              this.B = b;
          }
      
          [JsonProperty("a")]
          public String A { get; }
      
          [JsonProperty("a")]
          public String B { get; }
      }
      

      MyResponse.ts

      interface MyResponseFields {
          readonly a: string;
          readonly a: string;
      }
      
      interface MyResponse {
          readonly displayFields: MyResponseFields;
      }
      
  • 如果您始終displayFields動態的并且無法使用任何型別的靜態介面表示(即您確實想發送帶有鍵和值的任意 JSON ),則使用如下所示的內容:objectstringstring

    MyResponse.cs

    public class MyResponse
    {
        [JsonConstructor]
        public MyResponse(
            [JsonProperty("displayFields")] IReadOnlyDictionary<String,String> displayFields
        )
        {
            this.DisplayFields = displayFields ?? throw new ArgumentNullException(nameof(displayFields));
        }
    
        [JsonProperty("displayFields")]
        public IReadOnlyDictionary<String,String> DisplayFields { get; }
    }
    

    MyResponse.ts

    interface ReadonlyStringDictionaryObject {
        readonly [key: string]: string;
    }
    
    interface MyResponse {
        readonly displayFields: ReadonlyStringDictionaryObject;
    }
    

    并在 TypeScript 中像這樣使用(假設您正在使用fetch):

    async function getMyResponse(): MyResponse {
    
        const resp = fetch( '/my/service/endpoint' );
        if( resp.status === 200 && resp.headers.get('Content-Type')?.startsWith('application/json') ) {
            const json = await resp.json();
            if( isMyResponse( json ) ) {
                return json;
            }
        }
    
        throw new Error( "something went wrong" );
    }
    
    function isMyResponse( obj: unknown ): obj is MyResponse {
        return (
            typeof obj === 'object' && obj !== null && 'displayFields' in obj && ( typeof ( obj as any ).displayFields === 'object' );
        );
    }
    
    function convertMyResponseToMap( r: MyResponse ): Map<string,string> {
        return new Map( Object.entries( r.displayFields ) );
    }
    
    async function doStuff() {
    
        const myResponse = await getMyResponse();
        const asMap      = convertMyResponseToMap( myResponse );
    
        console.log( asMap );
    }
    
  • 還...

    • 在 JSON 中,物件屬性(又名鍵)應該始終是pascalCase,而不是TitleCase
    • 僅使用 TypeScriptinterface型別來描述 JSON 回應。避免使用,type因為這樣更容易無意中使用非 JSON 安全的技術和型別。
    • Also, TypeScript interfaces should describe immutable objects: all properties should be readonly, all collections should be readonly T[] and so on.
      • This is a good idea because it prevents things breaking in cases where you have two or more separate consumers of the same response object - where those consumers process the same response object-graph instance sequentially, and you don't want one altering the received response object such that it would break the other consumer.
        • TypeScript's type-system is not entirely "sound", and data-mutations are an easy way to encounter unsound situations. Keeping things immutable makes everything else easier.
    • 這也擴展到 C#:注意 DTOclass定義如何都是不可變的,使用建構式通過引數驗證來初始化自己,并且所有屬性都是只讀的。
      • [JsonConstructor][JsonProperty],如果你打算也由C#中反序列化JSON屬性在類的建構式時,才需要。
      • 如果您想知道為什么有這么多重復(與更簡單的可變C# DTO 類相比,請責怪 C# 語言設計者讓自定義建構式如此乏味——但是請考慮使用新的 C#record型別,因為這會減少很多乏味,但會限制您在建構式中執行驗證邏輯的能力。

uj5u.com熱心網友回復:

Axios使用方便的通用設計模式您可以提供回應的型別,但它不會在運行時強制執行 - 在型別安全方面它等同于型別斷言。

您的 C# 后端將 Dictionary 序列化為以下 JSON 字串:

{
   "A":"A Value",
   "B":"B Value"
}

由 Axios 決議為 JS 物件:

{
   A: "A Value",
   B: "B Value"
}

這正是您從回應中得到的記錄。

更一般地說,這意味著:

  • 如果您信任后端以正確的格式接收資料,則應指定回應的型別
  • 一個常見的陷阱是將類指定為回應型別 - 這不會像JSON.parse回傳普通物件那樣作業,而無需建立原型鏈。

您現在有 2 個選擇:

按原樣使用回傳的選項,指定正確的型別

正確的型別(匹配從 JSON.parse 實際回傳的資料)是索引型別:

type DisplayFields = {
   [key: string]: string
}

這是慣用的 TS,將使您能夠通過鍵訪問值。

將結果轉換為 Map

如果您依賴于Map在其余代碼中使用 a:

  • 對 Axios 請求使用索引型別
  • 收到回應后立即將其轉換為 Map。

注意:我不確定后端序列化的資料的形狀 - 如果它只是 Map 或包含 displayFields 屬性下的 Map 的物件。根據接收資料的形狀修改前端的回傳型別。

uj5u.com熱心網友回復:

您可以response.displayFields通過簡單地使用 Javascript 物件實作與 相同的輸出

const obj = {
      A: "A value",
      B: "B value"
}

和 typescript 型別定義一樣可以寫成:

const obj: Record<string, string> = {
      A: "A value",
      B: "B value"
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/399039.html

標籤:C# 反应 打字稿

上一篇:從動態物件更新物件的嵌套狀態陣列的多個屬性

下一篇:在Flutter中無需重繪即可更新串列視圖的SubTitle

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more