[{"data":1,"prerenderedAt":635},["ShallowReactive",2],{"page:\u002Fextensions\u002Fkubb-labs\u002Fplugin-fetch\u002Fguides\u002Fserialization":3},{"id":4,"title":5,"body":6,"description":616,"extension":624,"frontmatter":625,"heading":5,"meta":626,"navigation":627,"order":628,"path":629,"seo":630,"sitemap":631,"source":4,"stem":632,"__hash__":633,"hasPopups":634},"extensions\u002Fextensions\u002Fkubb-labs\u002Fplugin-fetch\u002Fguides\u002Fserialization.md","Configure serialization",{"type":7,"value":8,"toc":615},"minimark",[9,22,27,36,51,155,162,166,195,202,217,232,307,311,331,340,425,431,459,506,517,527,531,542,574,583,605],[10,11,12,13,17,18,21],"p",{},"The generated client encodes parameters using OpenAPI ",[14,15,16],"code",{},"style"," and ",[14,19,20],{},"explode",", serializes request bodies by content type, and decodes responses by media type. Each generated operation carries its parameter styles and content types, so most requests need no extra setup.",[23,24,26],"h2",{"id":25},"override-parameter-serialization","Override parameter serialization",[10,28,29,30,35],{},"Check the ",[31,32,34],"a",{"href":33},"https:\u002F\u002Fkubb.dev\u002Fdocs\u002F5.x\u002Freference\u002Fserialization#parameter-styles","default parameter styles and encoding"," before replacing a serializer.",[10,37,38,39,42,43,46,47,50],{},"Override ",[14,40,41],{},"serializer.query",", ",[14,44,45],{},".body",", or ",[14,48,49],{},".path"," on the client. Omitted functions retain their defaults:",[52,53,57],"pre",{"language":54,"code":55,"class":56},"typescript","import { client } from '.\u002Fgen\u002F.kubb\u002Fclient'\nimport qs from 'qs'\n\nclient.setConfig({\n  serializer: {\n    query: (params) => qs.stringify(params, { arrayFormat: 'brackets' }),\n  },\n})","shiki shiki-themes github-light github-dark dark:github-dark",[14,58,60,80,81,80,93,80,95,80,107,80,112,80,145,80,150],{"class":59},"language-typescript",[61,62,65,69,73,76],"span",{"class":63,"style":64},"line","display: inline",[61,66,68],{"style":67},"color:#D73A49;--shiki-dark:#F97583","import",[61,70,72],{"style":71},"color:#24292E;--shiki-dark:#E1E4E8"," { client } ",[61,74,75],{"style":67},"from",[61,77,79],{"style":78},"color:#032F62;--shiki-dark:#9ECBFF"," '.\u002Fgen\u002F.kubb\u002Fclient'","\n",[61,82,83,85,88,90],{"class":63,"style":64},[61,84,68],{"style":67},[61,86,87],{"style":71}," qs ",[61,89,75],{"style":67},[61,91,92],{"style":78}," 'qs'",[61,94],{"class":63,"style":64},[61,96,97,100,104],{"class":63,"style":64},[61,98,99],{"style":71},"client.",[61,101,103],{"style":102},"color:#6F42C1;--shiki-dark:#B392F0","setConfig",[61,105,106],{"style":71},"({",[61,108,109],{"class":63,"style":64},[61,110,111],{"style":71},"  serializer: {",[61,113,114,117,120,124,127,130,133,136,139,142],{"class":63,"style":64},[61,115,116],{"style":102},"    query",[61,118,119],{"style":71},": (",[61,121,123],{"style":122},"color:#E36209;--shiki-dark:#FFAB70","params",[61,125,126],{"style":71},") ",[61,128,129],{"style":67},"=>",[61,131,132],{"style":71}," qs.",[61,134,135],{"style":102},"stringify",[61,137,138],{"style":71},"(params, { arrayFormat: ",[61,140,141],{"style":78},"'brackets'",[61,143,144],{"style":71}," }),",[61,146,147],{"class":63,"style":64},[61,148,149],{"style":71},"  },",[61,151,152],{"class":63,"style":64},[61,153,154],{"style":71},"})",[10,156,157,158,161],{},"A serializer set this way runs for every call, but you can pass ",[14,159,160],{},"serializer"," on a single call to\noverride only that request.",[23,163,165],{"id":164},"encode-request-bodies","Encode request bodies",[10,167,168,169,172,173,176,177,172,180,183,184,42,186,42,188,42,191,194],{},"The request content type decides how the body is encoded. The default serializer handles the\ncommon types: a plain object becomes JSON, ",[14,170,171],{},"multipart\u002Fform-data"," becomes ",[14,174,175],{},"FormData",", and\n",[14,178,179],{},"application\u002Fx-www-form-urlencoded",[14,181,182],{},"URLSearchParams",". Binary and already-encoded bodies\n(",[14,185,175],{},[14,187,182],{},[14,189,190],{},"Blob",[14,192,193],{},"ArrayBuffer",", typed arrays, and strings) pass through\nuntouched.",[10,196,197,198,201],{},"When an operation declares a single request content type, Kubb sets it on the generated function,\nso you pass only the body. For an operation that accepts more than one, set ",[14,199,200],{},"contentType"," on the\ncall.",[203,204,206,207,209,210,213,214,216],"blockquote",{"as":205},"note","When the body is ",[14,208,175],{},", the runtime removes any ",[14,211,212],{},"Content-Type"," header so the transport sets\nit with the multipart boundary. You do not need to set ",[14,215,171],{}," yourself, and a\nvalue you set is dropped for that request.",[10,218,219,220,223,224,227,228,231],{},"To encode a content type the default serializer does not handle, register a codec for that media\ntype. ",[14,221,222],{},"codecs"," is keyed by content type. Each entry takes a ",[14,225,226],{},"serialize"," for the request body, a\n",[14,229,230],{},"deserialize"," for the response, or both:",[52,233,235],{"language":54,"code":234,"class":56},"import { client } from '.\u002Fgen\u002F.kubb\u002Fclient'\nimport { stringify } from 'yaml'\n\nclient.setConfig({\n  codecs: {\n    'application\u002Fyaml': { serialize: (body) => stringify(body) },\n  },\n})",[14,236,237,80,247,80,259,80,261,80,269,80,274,80,299,80,303],{"class":59},[61,238,239,241,243,245],{"class":63,"style":64},[61,240,68],{"style":67},[61,242,72],{"style":71},[61,244,75],{"style":67},[61,246,79],{"style":78},[61,248,249,251,254,256],{"class":63,"style":64},[61,250,68],{"style":67},[61,252,253],{"style":71}," { stringify } ",[61,255,75],{"style":67},[61,257,258],{"style":78}," 'yaml'",[61,260],{"class":63,"style":64},[61,262,263,265,267],{"class":63,"style":64},[61,264,99],{"style":71},[61,266,103],{"style":102},[61,268,106],{"style":71},[61,270,271],{"class":63,"style":64},[61,272,273],{"style":71},"  codecs: {",[61,275,276,279,282,284,286,289,291,293,296],{"class":63,"style":64},[61,277,278],{"style":78},"    'application\u002Fyaml'",[61,280,281],{"style":71},": { ",[61,283,226],{"style":102},[61,285,119],{"style":71},[61,287,288],{"style":122},"body",[61,290,126],{"style":71},[61,292,129],{"style":67},[61,294,295],{"style":102}," stringify",[61,297,298],{"style":71},"(body) },",[61,300,301],{"class":63,"style":64},[61,302,149],{"style":71},[61,304,305],{"class":63,"style":64},[61,306,154],{"style":71},[23,308,310],{"id":309},"decode-responses","Decode responses",[10,312,313,314,316,317,319,320,322,323,326,327,330],{},"The runtime reads the response ",[14,315,212],{}," and decodes the body by it: JSON is parsed, text\nstays a string, and a binary type becomes a ",[14,318,190],{},". The negotiated media type is on the result as\n",[14,321,200],{},", so a ",[14,324,325],{},"switch (result.contentType)"," narrows ",[14,328,329],{},"data"," for an operation that returns\nmore than one.",[10,332,333,334,336,337,339],{},"To decode a media type the runtime does not handle, register a codec's ",[14,335,230],{}," for it.\n",[14,338,230],{}," receives the raw body and the content type and returns the parsed value. It runs\nbefore validation, so the schema checks the parsed value:",[52,341,343],{"language":54,"code":342,"class":56},"import { client } from '.\u002Fgen\u002F.kubb\u002Fclient'\n\nclient.setConfig({\n  codecs: {\n    'application\u002Fxml': { deserialize: (raw) => new DOMParser().parseFromString(raw as string, 'application\u002Fxml') },\n  },\n})",[14,344,345,80,355,80,357,80,365,80,369,80,417,80,421],{"class":59},[61,346,347,349,351,353],{"class":63,"style":64},[61,348,68],{"style":67},[61,350,72],{"style":71},[61,352,75],{"style":67},[61,354,79],{"style":78},[61,356],{"class":63,"style":64},[61,358,359,361,363],{"class":63,"style":64},[61,360,99],{"style":71},[61,362,103],{"style":102},[61,364,106],{"style":71},[61,366,367],{"class":63,"style":64},[61,368,273],{"style":71},[61,370,371,374,376,378,380,383,385,387,390,393,396,399,402,405,409,411,414],{"class":63,"style":64},[61,372,373],{"style":78},"    'application\u002Fxml'",[61,375,281],{"style":71},[61,377,230],{"style":102},[61,379,119],{"style":71},[61,381,382],{"style":122},"raw",[61,384,126],{"style":71},[61,386,129],{"style":67},[61,388,389],{"style":67}," new",[61,391,392],{"style":102}," DOMParser",[61,394,395],{"style":71},"().",[61,397,398],{"style":102},"parseFromString",[61,400,401],{"style":71},"(raw ",[61,403,404],{"style":67},"as",[61,406,408],{"style":407},"color:#005CC5;--shiki-dark:#79B8FF"," string",[61,410,42],{"style":71},[61,412,413],{"style":78},"'application\u002Fxml'",[61,415,416],{"style":71},") },",[61,418,419],{"class":63,"style":64},[61,420,149],{"style":71},[61,422,423],{"class":63,"style":64},[61,424,154],{"style":71},[10,426,427,428,430],{},"Like the other config, ",[14,429,222],{}," can also be passed on a single call, and a per-call entry merges\nover the client one for that content type.",[10,432,433,434,436,437,440,441,42,444,447,448,42,451,454,455,458],{},"When the runtime picks the wrong parse mode because a response omits its ",[14,435,212],{}," or sets a\nmisleading one, force the mode with ",[14,438,439],{},"responseType"," on the call. It accepts ",[14,442,443],{},"'json'",[14,445,446],{},"'text'",",\n",[14,449,450],{},"'blob'",[14,452,453],{},"'arraybuffer'",", and ",[14,456,457],{},"'document'",":",[52,460,462],{"language":54,"code":461,"class":56},"const { data } = await downloadInvoice({ path: { id: '123' }, responseType: 'blob' })\n\u002F\u002F data is a Blob even when the server leaves Content-Type unset",[14,463,464,80,500],{"class":59},[61,465,466,469,472,474,477,480,483,486,489,492,495,497],{"class":63,"style":64},[61,467,468],{"style":67},"const",[61,470,471],{"style":71}," { ",[61,473,329],{"style":407},[61,475,476],{"style":71}," } ",[61,478,479],{"style":67},"=",[61,481,482],{"style":67}," await",[61,484,485],{"style":102}," downloadInvoice",[61,487,488],{"style":71},"({ path: { id: ",[61,490,491],{"style":78},"'123'",[61,493,494],{"style":71}," }, responseType: ",[61,496,450],{"style":78},[61,498,499],{"style":71}," })",[61,501,502],{"class":63,"style":64},[61,503,505],{"style":504},"color:#6A737D;--shiki-dark:#6A737D","\u002F\u002F data is a Blob even when the server leaves Content-Type unset",[10,507,508,512,513,516],{},[31,509,511],{"href":510},"https:\u002F\u002Fkubb.dev\u002Fextensions\u002Fkubb-labs\u002Fplugin-fetch\u002Fguides\u002Fserver-sent-events","Server-sent events"," covers ",[14,514,515],{},"responseType: 'stream'",".",[10,518,519,520,17,522,524,525,516],{},"For bidirectional formats, supply both ",[14,521,226],{},[14,523,230],{}," in the media type codec, then set the operation's request and response ",[14,526,200],{},[23,528,530],{"id":529},"validate-responses","Validate responses",[10,532,533,534,537,538,541],{},"Enable ",[14,535,536],{},"validator"," on the client plugin and register ",[14,539,540],{},"pluginZod"," in the same configuration. Validation is disabled by default.",[52,543,545],{"language":54,"code":544,"class":56},"import { pluginFetch } from '@kubb\u002Fplugin-fetch'\n\npluginFetch({ validator: 'zod' })",[14,546,547,80,559,80,561],{"class":59},[61,548,549,551,554,556],{"class":63,"style":64},[61,550,68],{"style":67},[61,552,553],{"style":71}," { pluginFetch } ",[61,555,75],{"style":67},[61,557,558],{"style":78}," '@kubb\u002Fplugin-fetch'",[61,560],{"class":63,"style":64},[61,562,563,566,569,572],{"class":63,"style":64},[61,564,565],{"style":102},"pluginFetch",[61,567,568],{"style":71},"({ validator: ",[61,570,571],{"style":78},"'zod'",[61,573,499],{"style":71},[10,575,576,578,579,582],{},[14,577,571],{}," validates the success response body, and the error body when a non-2xx call does not\nthrow. Use the object form to opt in per direction, where ",[14,580,581],{},"request"," validates the request\nbody before the call goes out:",[52,584,586],{"language":54,"code":585,"class":56},"pluginFetch({ validator: { request: 'zod', response: 'zod' } })",[14,587,588],{"class":59},[61,589,590,592,595,597,600,602],{"class":63,"style":64},[61,591,565],{"style":102},[61,593,594],{"style":71},"({ validator: { request: ",[61,596,571],{"style":78},[61,598,599],{"style":71},", response: ",[61,601,571],{"style":78},[61,603,604],{"style":71}," } })",[10,606,607,608,611,612,516],{},"With a validator set, Kubb passes the matching schema to each generated call, and the runtime\nparses the body through it. A body that does not match throws a ",[14,609,610],{},"ParseError"," with the schema's\n",[14,613,614],{},"issues",{"title":616,"searchDepth":617,"depth":617,"links":618},"",5,[619,621,622,623],{"id":25,"depth":620,"text":26},2,{"id":164,"depth":620,"text":165},{"id":309,"depth":620,"text":310},{"id":529,"depth":620,"text":530},"md",{},{},true,null,"\u002Fextensions\u002Fkubb-labs\u002Fplugin-fetch\u002Fguides\u002Fserialization",{"title":5},{"loc":629},"extensions\u002Fkubb-labs\u002Fplugin-fetch\u002Fguides\u002Fserialization","MazRZgjgx2HTSuxWNWpmbQbtQE8Ti-eOgBcXbmmOwIw",false,1792733921235]