Files
amiibo-service/docs/data/documentation/amiiboservice.json
T
javierandjavier 0c41e5d4ce Several fixes and optimizations all over the library (#28)
This PR contains the work done to cleans up the library after the Swift 6.2 migration: drops the legacy conditional-compilation paths, hardens the OpenAPI specification, removes boilerplate from the live client, and makes the live test suite resilient to changes in the upstream service data.

* Swift 6.2 baseline
  * Adopted swift-tools-version: 6.2, which allowed removing every #if swift(>=6.0) / #if swift(>=6.2) branch and natural-language test names are now the only code paths.
  * `AmiiboClient` client now refines `Sendable`, and both `AmiiboLiveClient` and `AmiiboService` conform to it, so instances can be shared across concurrency domains.

* Live client
  * Extracted a generic `perform(_:)` helper that wraps every generated API call and funnels transport errors through the existing error mapper — replaces six repeated do/catch blocks and lets the private fetch* methods use typed throws end-to-end.
  * Added the internal `KeyNamePayload` protocol and a generic makeModels(from:), collapsing the four near-identical mapping/sorting blocks for amiibo series, types, game characters and game series into one.
  * The server URL is now resolved once into a static let constant instead of on every initialization.
  * Improved error mapping: URLError.cancelled → .cancelled, .cannotParseResponse → .decoding, and .dataNotAllowed, .internationalRoamingOff, .secureConnectionFailed now map to .notAvailable.
  * Simplified the Amiibo.Platform initializer ([Amiibo+Platform.swift](vscode-webview://1m6rk4uhpaukb4hrbp3j54p77iq693fq2ql7o9oup2pca1omf7f6/Sources/AmiiboService/Public/Models/Amiibo/Amiibo+Platform.swift)) using optional chaining and ?? [] instead of nested guards and immediately-invoked closures.
  * Set the en_US_POSIX locale on both fixed-format date formatters so the user's locale or 12/24-hour setting can no longer break parsing.

* OpenAPI specification
  * Replaced the shared Tuple schema with explicit per-type schemas (AmiiboSeries, AmiiboType, GameCharacter, GameSeries), so the generated code exposes real properties instead of allOf wrappers with .value1 accessors.
  * Extracted named list schemas (AmiiboList, AmiiboSeriesList, …) for the wrapper payloads, which turns the generated .case2 enum cases into readable .AmiiboSeriesList cases.
  * Added validation patterns and length bounds to the id, head, tail and key query parameters, and collapsed the redundant pattern/minLength/maxLength triplets on head/tail into ^[0-9a-fA-F]{8}$.
  * Extracted the shared InternalServerError response, replacing the five inline 500 descriptions.
  * Documented the two non-standard date/time decoding behaviours (date-only strings for release dates, offset-less timestamps for lastUpdated) and why the optional amiibo wrapper property must stay optional.
  * Corrected the info.version value from v1.0.0 to 1.0.0.

* ⚠️ Breaking changes
  *  Minimum Swift version raised from 5.10 to 6.2.
  *  `AmiiboServiceError.unknown` now carries a String description of the underlying error.
  *  `AmiiboClient` requires Sendable conformance, so existing custom mock clients must be Sendable.

Reviewed-on: #28
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
2026-07-26 09:56:32 +00:00

1 line
20 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"sections":[],"primaryContentSections":[{"content":[{"type":"heading","text":"Overview","anchor":"Overview","level":2},{"type":"paragraph","inlineContent":[{"text":"The ","type":"text"},{"code":"amiibo-service","type":"codeVoice"},{"text":" library is a package that allows the developer to interact with the ","type":"text"},{"type":"reference","identifier":"https:\/\/www.amiiboapi.org","isActive":true},{"text":" backend service seamlessly, by not only providing the ","type":"text"},{"inlineContent":[{"type":"text","text":"service"}],"type":"emphasis"},{"text":" type but also any possible ","type":"text"},{"inlineContent":[{"type":"text","text":"models"}],"type":"emphasis"},{"text":", ","type":"text"},{"inlineContent":[{"type":"text","text":"filters"}],"type":"emphasis"},{"text":", ","type":"text"},{"inlineContent":[{"type":"text","text":"errors"}],"type":"emphasis"},{"text":" and ","type":"text"},{"inlineContent":[{"type":"text","text":"interfaces"}],"type":"emphasis"},{"text":" types that might be needed during implementation.","type":"text"}]},{"type":"heading","text":"Design","anchor":"Design","level":2},{"type":"paragraph","inlineContent":[{"text":"Although it could have been possible to generate a one-to-one RESTful client based on the Open API specification document that describe the available endpoints of the backend service, it was decided to design a ","type":"text"},{"code":"AmiiboService","type":"codeVoice"},{"text":" service type that removes the complexities of the API design imposed by the backend service, and provides the developer with a simple interface, and a seamless experience.","type":"text"}]},{"type":"heading","text":"Installation","anchor":"Installation","level":2},{"type":"paragraph","inlineContent":[{"text":"To use the ","type":"text"},{"code":"AmiiboService","type":"codeVoice"},{"text":" library with your package, then add it as a dependency in the ","type":"text"},{"code":"Package.swift","type":"codeVoice"},{"text":" file:","type":"text"}]},{"type":"codeListing","syntax":"swift","code":["let package = Package("," \/\/ name, platforms, products, etc."," dependencies: ["," .package(url: \"https:\/\/github.com\/rock-n-code\/amiibo-service\", from: \"2.0.0\"),"," \/\/ other dependencies"," ],"," targets: ["," .target("," name: \"SomeTarget\", "," dependencies: ["," .product(name: \"AmiiboService\", package: \"amiibo-service\"),"," ]"," )"," \/\/ other targets"," ]",")"]},{"type":"paragraph","inlineContent":[{"text":"It is also possible to use the ","type":"text"},{"code":"AmiiboService","type":"codeVoice"},{"text":" library with your app in Xcode, then add it as a dependency in your Xcode project.","type":"text"}]},{"type":"aside","style":"important","name":"Important","content":[{"inlineContent":[{"type":"text","text":"Swift 6.2 or higher is required in order to compile this library."}],"type":"paragraph"}]},{"type":"heading","text":"Usage","anchor":"Usage","level":2},{"type":"paragraph","inlineContent":[{"text":"Create an ","type":"text"},{"type":"reference","identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboService","isActive":true},{"text":" instance and call any of its endpoints. Each endpoint accepts an optional filter and, when omitted, returns the full set of results:","type":"text"}]},{"type":"codeListing","syntax":"swift","code":["import AmiiboService","","let service = AmiiboService()","","\/\/ Fetch all amiibos","let amiibos = try await service.getAmiibos()","","\/\/ Fetch amiibos filtered by name","let zeldaAmiibos = try await service.getAmiibos(.init(name: \"zelda\"))","","\/\/ Fetch amiibo series, types, game characters, and game series","let series = try await service.getAmiiboSeries()","let types = try await service.getAmiiboTypes()","let characters = try await service.getGameCharacters()","let gameSeries = try await service.getGameSeries()","","\/\/ Fetch the last updated timestamp","let lastUpdated = try await service.getLastUpdated()"]},{"type":"heading","text":"Caching","anchor":"Caching","level":2},{"type":"paragraph","inlineContent":[{"text":"The ","type":"text"},{"overridingTitle":"Amiibo API","overridingTitleInlineContent":[{"type":"text","text":"Amiibo API"}],"type":"reference","identifier":"https:\/\/www.amiiboapi.org","isActive":true},{"text":" recommends that consumers who call the API regularly implement caching on their systems. This library does not include a built-in cache, leaving the choice of caching strategy to the consumer. The following examples show two common approaches.","type":"text"}]},{"type":"heading","text":"URLCache on the transport layer","anchor":"URLCache-on-the-transport-layer","level":3},{"type":"paragraph","inlineContent":[{"text":"Pass a custom ","type":"text"},{"code":"URLSessionTransport","type":"codeVoice"},{"text":" with a cache-configured ","type":"text"},{"code":"URLSession","type":"codeVoice"},{"text":" to ","type":"text"},{"type":"reference","identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboLiveClient","isActive":true},{"text":":","type":"text"}]},{"type":"codeListing","syntax":"swift","code":["import OpenAPIURLSession","","let configuration = URLSessionConfiguration.default","","configuration.urlCache = URLCache("," memoryCapacity: 5_000_000,"," diskCapacity: 50_000_000",")","","let transport = URLSessionTransport("," configuration: .init("," session: URLSession(configuration: configuration)"," )",")","","let service = AmiiboService("," client: AmiiboLiveClient(transport: transport)",")"]},{"type":"paragraph","inlineContent":[{"text":"This leverages HTTP cache headers from the server and persists cached responses to disk.","type":"text"}]},{"type":"heading","text":"Application-level caching","anchor":"Application-level-caching","level":3},{"type":"paragraph","inlineContent":[{"text":"Alternatively, cache the results returned by ","type":"text"},{"type":"reference","identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboService","isActive":true},{"text":" directly in your application using any storage mechanism that fits your needs, such as an in-memory dictionary, a database, or a file-based store.","type":"text"}]},{"type":"heading","text":"Testing","anchor":"Testing","level":2},{"type":"paragraph","inlineContent":[{"text":"The ","type":"text"},{"type":"reference","identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboClient","isActive":true},{"text":" protocol enables creating custom mock clients for testing, eliminating the need for network calls in unit tests. Conform to ","type":"text"},{"type":"reference","identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboClient","isActive":true},{"text":" and return stubbed data or throw ","type":"text"},{"type":"reference","identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboServiceError","isActive":true},{"text":" errors to verify your applications behavior:","type":"text"}]},{"type":"codeListing","syntax":"swift","code":["import AmiiboService","","struct MyMockClient: AmiiboClient {"," var error: AmiiboServiceError?",""," func getAmiibos("," by filter: AmiiboFilter"," ) async throws(AmiiboServiceError) -> [Amiibo] {"," if let error { throw error }"," return []"," }",""," \/\/ Implement remaining protocol requirements...","}","","let service = AmiiboService(client: MyMockClient())"]},{"type":"paragraph","inlineContent":[{"text":"Inject the mock client into ","type":"text"},{"type":"reference","identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboService","isActive":true},{"text":" via its ","type":"text"},{"type":"reference","identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboService\/init(client:)","isActive":true},{"text":" initializer to test how your code handles empty results, specific errors, or any other scenario without relying on the live backend.","type":"text"}]},{"type":"heading","text":"Tasks","anchor":"Tasks","level":2},{"type":"paragraph","inlineContent":[{"text":"This library offers a set of ready-to-use tasks that simplify the interaction with the library, which the developer can use from any ","type":"text"},{"code":"Terminal","type":"codeVoice"},{"text":" application.","type":"text"}]},{"type":"aside","style":"tip","name":"Tip","content":[{"inlineContent":[{"type":"text","text":"To show the available list of tasks, plus display some explanations about each and every one of them; please enter the following command:"}],"type":"paragraph"}]},{"type":"codeListing","syntax":"bash","code":["$ make"]}],"kind":"content"}],"abstract":[{"type":"text","text":"A library that provides everything the developer needs to interact with the "},{"type":"strong","inlineContent":[{"text":"Amiibo API","type":"text"}]},{"type":"text","text":" backend service."}],"kind":"symbol","schemaVersion":{"minor":3,"patch":0,"major":0},"identifier":{"url":"doc:\/\/AmiiboService\/documentation\/AmiiboService","interfaceLanguage":"swift"},"hierarchy":{"paths":[[]]},"metadata":{"symbolKind":"module","roleHeading":"Framework","title":"AmiiboService","role":"collection","externalID":"AmiiboService","modules":[{"name":"AmiiboService"}]},"topicSections":[{"anchor":"Service","identifiers":["doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboService"],"title":"Service"},{"anchor":"Clients","identifiers":["doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboClient","doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboLiveClient"],"title":"Clients"},{"anchor":"Models","identifiers":["doc:\/\/AmiiboService\/documentation\/AmiiboService\/Amiibo","doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboSeries","doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboType","doc:\/\/AmiiboService\/documentation\/AmiiboService\/GameCharacter","doc:\/\/AmiiboService\/documentation\/AmiiboService\/GameSeries"],"title":"Models"},{"anchor":"Filters","identifiers":["doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboFilter","doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboSeriesFilter","doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboTypeFilter","doc:\/\/AmiiboService\/documentation\/AmiiboService\/GameCharacterFilter","doc:\/\/AmiiboService\/documentation\/AmiiboService\/GameSeriesFilter"],"title":"Filters"},{"anchor":"Errors","identifiers":["doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboServiceError"],"title":"Errors"}],"variants":[{"paths":["\/documentation\/amiiboservice"],"traits":[{"interfaceLanguage":"swift"}]}],"references":{"https://www.amiiboapi.org":{"url":"https:\/\/www.amiiboapi.org","identifier":"https:\/\/www.amiiboapi.org","titleInlineContent":[{"type":"text","text":"Amiibo API"}],"type":"link","title":"Amiibo API"},"doc://AmiiboService/documentation/AmiiboService/AmiiboClient":{"fragments":[{"text":"protocol","kind":"keyword"},{"text":" ","kind":"text"},{"text":"AmiiboClient","kind":"identifier"}],"url":"\/documentation\/amiiboservice\/amiiboclient","role":"symbol","type":"topic","title":"AmiiboClient","abstract":[{"type":"text","text":"A protocol that defines API clients containing all available endpoints to interact with."}],"kind":"symbol","navigatorTitle":[{"text":"AmiiboClient","kind":"identifier"}],"identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboClient"},"doc://AmiiboService/documentation/AmiiboService/AmiiboLiveClient":{"fragments":[{"text":"struct","kind":"keyword"},{"text":" ","kind":"text"},{"text":"AmiiboLiveClient","kind":"identifier"}],"url":"\/documentation\/amiiboservice\/amiiboliveclient","role":"symbol","type":"topic","title":"AmiiboLiveClient","abstract":[{"type":"text","text":"A type that implements a live client to the "},{"isActive":true,"type":"reference","identifier":"https:\/\/www.amiiboapi.org"},{"type":"text","text":" online service."}],"kind":"symbol","navigatorTitle":[{"text":"AmiiboLiveClient","kind":"identifier"}],"identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboLiveClient"},"doc://AmiiboService/documentation/AmiiboService/Amiibo":{"fragments":[{"text":"struct","kind":"keyword"},{"kind":"text","text":" "},{"text":"Amiibo","kind":"identifier"}],"url":"\/documentation\/amiiboservice\/amiibo","navigatorTitle":[{"kind":"identifier","text":"Amiibo"}],"type":"topic","abstract":[{"type":"text","text":"A model that represents an amiibo."}],"identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/Amiibo","kind":"symbol","title":"Amiibo","role":"symbol"},"doc://AmiiboService/documentation/AmiiboService/GameCharacterFilter":{"role":"symbol","navigatorTitle":[{"kind":"identifier","text":"GameCharacterFilter"}],"abstract":[{"type":"text","text":"A type that contains values to fine-tune a response when requesting game characters."}],"title":"GameCharacterFilter","url":"\/documentation\/amiiboservice\/gamecharacterfilter","type":"topic","identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/GameCharacterFilter","fragments":[{"kind":"keyword","text":"struct"},{"kind":"text","text":" "},{"kind":"identifier","text":"GameCharacterFilter"}],"kind":"symbol"},"doc://AmiiboService/documentation/AmiiboService/AmiiboTypeFilter":{"fragments":[{"kind":"keyword","text":"struct"},{"kind":"text","text":" "},{"kind":"identifier","text":"AmiiboTypeFilter"}],"url":"\/documentation\/amiiboservice\/amiibotypefilter","navigatorTitle":[{"kind":"identifier","text":"AmiiboTypeFilter"}],"type":"topic","abstract":[{"type":"text","text":"A type that contains values to fine-tune a response when requesting amiibo types."}],"identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboTypeFilter","kind":"symbol","title":"AmiiboTypeFilter","role":"symbol"},"doc://AmiiboService/documentation/AmiiboService/AmiiboService/init(client:)":{"fragments":[{"text":"init","kind":"identifier"},{"text":"(","kind":"text"},{"text":"client","kind":"externalParam"},{"text":": ","kind":"text"},{"text":"some","kind":"keyword"},{"text":" ","kind":"text"},{"preciseIdentifier":"s:13AmiiboService0A6ClientP","text":"AmiiboClient","kind":"typeIdentifier"},{"text":")","kind":"text"}],"url":"\/documentation\/amiiboservice\/amiiboservice\/init(client:)","type":"topic","abstract":[{"text":"Initializes this service with a specific client type.","type":"text"}],"identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboService\/init(client:)","kind":"symbol","title":"init(client:)","role":"symbol"},"doc://AmiiboService/documentation/AmiiboService":{"abstract":[{"type":"text","text":"A library that provides everything the developer needs to interact with the "},{"type":"strong","inlineContent":[{"type":"text","text":"Amiibo API"}]},{"type":"text","text":" backend service."}],"type":"topic","identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService","url":"\/documentation\/amiiboservice","kind":"symbol","title":"AmiiboService","role":"collection"},"doc://AmiiboService/documentation/AmiiboService/AmiiboSeriesFilter":{"fragments":[{"text":"struct","kind":"keyword"},{"text":" ","kind":"text"},{"kind":"identifier","text":"AmiiboSeriesFilter"}],"url":"\/documentation\/amiiboservice\/amiiboseriesfilter","role":"symbol","type":"topic","title":"AmiiboSeriesFilter","abstract":[{"type":"text","text":"A type that contains values to fine-tune a response when requesting amiibo series."}],"kind":"symbol","navigatorTitle":[{"text":"AmiiboSeriesFilter","kind":"identifier"}],"identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboSeriesFilter"},"doc://AmiiboService/documentation/AmiiboService/GameSeries":{"type":"topic","identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/GameSeries","abstract":[{"text":"A model that represents a game series.","type":"text"}],"url":"\/documentation\/amiiboservice\/gameseries","fragments":[{"text":"struct","kind":"keyword"},{"text":" ","kind":"text"},{"text":"GameSeries","kind":"identifier"}],"kind":"symbol","title":"GameSeries","navigatorTitle":[{"text":"GameSeries","kind":"identifier"}],"role":"symbol"},"doc://AmiiboService/documentation/AmiiboService/AmiiboFilter":{"role":"symbol","navigatorTitle":[{"text":"AmiiboFilter","kind":"identifier"}],"url":"\/documentation\/amiiboservice\/amiibofilter","identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboFilter","title":"AmiiboFilter","abstract":[{"type":"text","text":"A type that contains values to fine-tune a response when requesting amiibo items."}],"type":"topic","fragments":[{"text":"struct","kind":"keyword"},{"kind":"text","text":" "},{"text":"AmiiboFilter","kind":"identifier"}],"kind":"symbol"},"doc://AmiiboService/documentation/AmiiboService/GameSeriesFilter":{"role":"symbol","navigatorTitle":[{"text":"GameSeriesFilter","kind":"identifier"}],"url":"\/documentation\/amiiboservice\/gameseriesfilter","abstract":[{"type":"text","text":"A type that contains values to fine-tune a response when requesting game series."}],"identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/GameSeriesFilter","type":"topic","title":"GameSeriesFilter","fragments":[{"text":"struct","kind":"keyword"},{"text":" ","kind":"text"},{"text":"GameSeriesFilter","kind":"identifier"}],"kind":"symbol"},"doc://AmiiboService/documentation/AmiiboService/GameCharacter":{"type":"topic","navigatorTitle":[{"text":"GameCharacter","kind":"identifier"}],"kind":"symbol","title":"GameCharacter","fragments":[{"kind":"keyword","text":"struct"},{"text":" ","kind":"text"},{"kind":"identifier","text":"GameCharacter"}],"identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/GameCharacter","url":"\/documentation\/amiiboservice\/gamecharacter","role":"symbol","abstract":[{"type":"text","text":"A model that represents a game character."}]},"doc://AmiiboService/documentation/AmiiboService/AmiiboService":{"type":"topic","navigatorTitle":[{"text":"AmiiboService","kind":"identifier"}],"title":"AmiiboService","kind":"symbol","fragments":[{"kind":"keyword","text":"struct"},{"kind":"text","text":" "},{"text":"AmiiboService","kind":"identifier"}],"identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboService","url":"\/documentation\/amiiboservice\/amiiboservice","role":"symbol","abstract":[{"text":"A type that implements the service that uses a client to make calls.","type":"text"}]},"doc://AmiiboService/documentation/AmiiboService/AmiiboSeries":{"fragments":[{"text":"struct","kind":"keyword"},{"text":" ","kind":"text"},{"text":"AmiiboSeries","kind":"identifier"}],"url":"\/documentation\/amiiboservice\/amiiboseries","navigatorTitle":[{"text":"AmiiboSeries","kind":"identifier"}],"type":"topic","abstract":[{"type":"text","text":"A model that represents an amiibo series."}],"identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboSeries","kind":"symbol","title":"AmiiboSeries","role":"symbol"},"doc://AmiiboService/documentation/AmiiboService/AmiiboServiceError":{"fragments":[{"kind":"keyword","text":"enum"},{"kind":"text","text":" "},{"kind":"identifier","text":"AmiiboServiceError"}],"url":"\/documentation\/amiiboservice\/amiiboserviceerror","role":"symbol","type":"topic","title":"AmiiboServiceError","abstract":[{"type":"text","text":"A representation of all the possible errors that the "},{"isActive":true,"type":"reference","identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboService"},{"type":"text","text":" service could throw."}],"kind":"symbol","navigatorTitle":[{"text":"AmiiboServiceError","kind":"identifier"}],"identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboServiceError"},"doc://AmiiboService/documentation/AmiiboService/AmiiboType":{"role":"symbol","navigatorTitle":[{"text":"AmiiboType","kind":"identifier"}],"abstract":[{"text":"A model that represents an amiibo type.","type":"text"}],"identifier":"doc:\/\/AmiiboService\/documentation\/AmiiboService\/AmiiboType","title":"AmiiboType","type":"topic","url":"\/documentation\/amiiboservice\/amiibotype","fragments":[{"text":"struct","kind":"keyword"},{"text":" ","kind":"text"},{"text":"AmiiboType","kind":"identifier"}],"kind":"symbol"}}}