Update JSON usage from Any to JSONValue#740
Conversation
Renamed to avoid conflicts with the existing JSON.swift file in Shared
There was a problem hiding this comment.
Pull request overview
This PR migrates JSON handling across the Readium Swift codebase from untyped Any / [String: Any] to the type-safe JSONValue, and relocates/renames the JSONDictionary helper into ReadiumShared to support Equatable/Hashable JSON-backed models.
Changes:
- Introduces
JSONDictionary(now backed by[String: JSONValue]) plus updated parsing/encoding helpers, and removes the old internalJSON.swift. - Updates core publication models, parsers, and format sniffers to parse/serialize via
JSONValue(with compatibilityinit(json: Any?)kept in many places). - Updates test fixtures and assertion helpers to work with
JSONValue-based JSON structures and normalization.
Reviewed changes
Copilot reviewed 75 out of 75 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| Tests/StreamerTests/Parser/Image/ComicInfoParserTests.swift | Adjusts test expectations for otherMetadata to use JSONValue accessors. |
| Tests/StreamerTests/Parser/EPUB/Services/EPUBPositionsServiceTests.swift | Updates test helper properties to build JSONValue objects/arrays. |
| Tests/StreamerTests/Parser/EPUB/EPUBMetadataParserTests.swift | Rewrites metadata fixtures to use .object/.array/.string JSONValue literals. |
| Tests/StreamerTests/Parser/EPUB/EPUBManifestParserTests.swift | Rewrites manifest fixtures to use JSONValue. |
| Tests/StreamerTests/Asserts.swift | Normalizes Any via JSONValue(...).any before JSONSerialization compare. |
| Tests/SharedTests/Publication/Services/Content/Iterators/HTMLResourceContentIteratorTests.swift | Updates locator otherLocations test data to .string. |
| Tests/SharedTests/Publication/LocatorTests.swift | Updates minimal JSON expectation to align with new encoding rules. |
| Tests/SharedTests/Publication/Extensions/OPDS/Properties+OPDSTests.swift | Removes legacy [String: Any] cast in test fixture. |
| Tests/SharedTests/Publication/Extensions/HTML/Locator+HTMLTests.swift | Removes legacy [String: Any] cast in test fixture. |
| Tests/SharedTests/Publication/Extensions/EPUB/Metadata+EPUBTests.swift | Updates EPUBMediaOverlay JSON fixtures to new typed JSON forms. |
| Tests/SharedTests/Publication/Extensions/Archive/Properties+ArchiveTests.swift | Removes legacy [String: Any] cast in test fixture. |
| Tests/SharedTests/Asserts.swift | Updates file default and normalizes Any via JSONValue before compare. |
| Support/Carthage/Readium.xcodeproj/project.pbxproj | Moves JSONDictionary.swift into Shared target sources; removes Internal JSON.swift. |
| Support/Carthage/.xcodegen | Updates XcodeGen inputs to reflect JSONDictionary move/rename. |
| Sources/Streamer/Parser/Readium/ReadiumWebPubParser.swift | Switches manifest decoding to asJSONObjectValue() and wraps into .object. |
| Sources/Streamer/Parser/Readium/ReadiumGuidedNavigationService.swift | Switches JSON decoding to asJSONObjectValue() and wraps into .object. |
| Sources/Streamer/Parser/Image/ComicInfoParser.swift | Encodes ComicInfo otherMetadata as [String: JSONValue] strings. |
| Sources/Streamer/Parser/EPUB/OPFParser.swift | Encodes properties/encryption using JSONValue objects/arrays. |
| Sources/Streamer/Parser/EPUB/OPFMeta.swift | Converts unknown metadata aggregation to [String: JSONValue]. |
| Sources/Streamer/Parser/EPUB/EPUBMetadataParser.swift | Wraps mediaOverlay JSON into .object in otherMetadata. |
| Sources/Shared/Toolkit/JSONDictionary.swift | Adds new Shared JSONDictionary + parse/encode helper APIs using JSONValue. |
| Sources/Shared/Toolkit/JSON.swift | Updates serialization + JSONEquatable to better interop with JSONValue. |
| Sources/Shared/Toolkit/Format/Sniffers/RWPMFormatSniffer.swift | Uses asJSONObjectValue() and wraps into .object for Manifest init. |
| Sources/Shared/Toolkit/Format/Sniffers/RPFFormatSniffer.swift | Uses asJSONObjectValue() and wraps into .object for Manifest init. |
| Sources/Shared/Toolkit/Format/Sniffers/OPDSFormatSniffer.swift | Uses asJSONObjectValue() and wraps into .object for Manifest init. |
| Sources/Shared/Toolkit/Format/Sniffers/LCPLicenseFormatSniffer.swift | Adjusts JSON reading path and guards with updated optional handling. |
| Sources/Shared/Toolkit/Format/Sniffers/JSONFormatSniffer.swift | Updates to reflect readAsJSON() now yielding JSONValue?. |
| Sources/Shared/Toolkit/Format/FormatSnifferBlob.swift | Changes cached JSON from Any? to JSONValue?. |
| Sources/Shared/Toolkit/Archive/ArchiveProperties.swift | Migrates ArchiveProperties JSON parsing/encoding to JSONValue. |
| Sources/Shared/Publication/TDM.swift | Migrates TDM JSON parsing/encoding to JSONValue with Any convenience init. |
| Sources/Shared/Publication/Subject.swift | Migrates Subject parsing/encoding to JSONValue with Any convenience init. |
| Sources/Shared/Publication/Services/Positions/PositionsService.swift | Emits/consumes positions JSON using JSONValue and asJSONObjectValue(). |
| Sources/Shared/Publication/Services/Content/Iterators/HTMLResourceContentIterator.swift | Makes locator otherLocations cssSelector explicitly typed JSONValue. |
| Sources/Shared/Publication/PublicationCollection.swift | Migrates collection JSON parsing/encoding to JSONValue with Any convenience init. |
| Sources/Shared/Publication/Publication.swift | Adds init(json: JSONValue) and bridges Any to JSONValue. |
| Sources/Shared/Publication/Properties.swift | Migrates properties storage and subscript to JSONValue. |
| Sources/Shared/Publication/Metadata.swift | Migrates metadata parsing/encoding to JSONValue with Any convenience init. |
| Sources/Shared/Publication/Manifest.swift | Migrates manifest parsing/encoding to JSONValue with Any convenience init. |
| Sources/Shared/Publication/Locator.swift | Migrates locator + nested types parsing/encoding to JSONValue with Any convenience inits. |
| Sources/Shared/Publication/LocalizedString.swift | Migrates LocalizedString parsing/encoding to JSONValue with Any convenience init. |
| Sources/Shared/Publication/LinkRelation.swift | Migrates LinkRelation array parsing to JSONValue with Any convenience init. |
| Sources/Shared/Publication/Link.swift | Migrates Link parsing/encoding to JSONValue with Any convenience init. |
| Sources/Shared/Publication/GuidedNavigation/GuidedNavigationObject.swift | Migrates guided navigation object parsing to JSONValue with Any convenience init. |
| Sources/Shared/Publication/GuidedNavigation/GuidedNavigationDocument.swift | Migrates guided navigation document parsing to JSONValue with Any convenience init. |
| Sources/Shared/Publication/Extensions/Presentation/Properties+Presentation.swift | Updates property access to JSONValue.bool. |
| Sources/Shared/Publication/Extensions/Presentation/Presentation.swift | Migrates Presentation parsing/encoding to JSONValue with Any convenience init. |
| Sources/Shared/Publication/Extensions/HTML/Locator+HTML.swift | Updates otherLocations access to JSONValue.string. |
| Sources/Shared/Publication/Extensions/HTML/DOMRange.swift | Migrates DOMRange parsing/encoding to JSONValue with Any convenience init. |
| Sources/Shared/Publication/Extensions/Encryption/Encryption.swift | Migrates Encryption parsing/encoding to JSONValue with Any convenience init. |
| Sources/Shared/Publication/Extensions/EPUB/EPUBMediaOverlay.swift | Migrates EPUBMediaOverlay parsing/encoding to JSONValue with Any convenience init. |
| Sources/Shared/Publication/Extensions/Archive/Properties+Archive.swift | Migrates archive properties parsing/encoding to JSONValue with Any convenience init. |
| Sources/Shared/Publication/Contributor.swift | Migrates Contributor parsing/encoding to JSONValue with Any convenience init. |
| Sources/Shared/Publication/Accessibility/Accessibility.swift | Migrates Accessibility parsing/encoding to JSONValue with Any convenience init. |
| Sources/Shared/OPDS/OPDSPrice.swift | Migrates OPDSPrice parsing/encoding to JSONValue. |
| Sources/Shared/OPDS/OPDSHolds.swift | Migrates OPDSHolds parsing to JSONValue-backed JSONDictionary. |
| Sources/Shared/OPDS/OPDSCopies.swift | Migrates OPDSCopies parsing to JSONValue-backed JSONDictionary. |
| Sources/Shared/OPDS/OPDSAvailability.swift | Migrates OPDSAvailability parsing to JSONValue-backed JSONDictionary. |
| Sources/Shared/OPDS/OPDSAcquisition.swift | Migrates OPDSAcquisition encoding to JSONValue and adjusts parsing. |
| Sources/OPDS/OPDS1Parser.swift | Emits OPDS link properties using [String: JSONValue]. |
| Sources/Navigator/EPUB/HTMLDecorationTemplate.swift | Migrates decoration template JSON output to [String: JSONValue]. |
| Sources/LCP/License/Model/StatusDocument.swift | Migrates LSD parsing to JSONValue-backed JSONDictionary and helpers. |
| Sources/LCP/License/Model/LicenseDocument.swift | Migrates license document parsing to JSONValue-backed JSONDictionary and helpers. |
| Sources/LCP/License/Model/Components/Links.swift | Adds JSONValue-based Links initializer; bridges legacy initializer. |
| Sources/LCP/License/Model/Components/Link.swift | Adds JSONValue-based Link initializer; bridges legacy initializer. |
| Sources/LCP/License/Model/Components/LSD/PotentialRights.swift | Adds JSONValue-based initializer; bridges legacy initializer. |
| Sources/LCP/License/Model/Components/LSD/Event.swift | Adds JSONValue-based initializer; bridges legacy initializer. |
| Sources/LCP/License/Model/Components/LCP/UserKey.swift | Adds JSONValue-based initializer; bridges legacy initializer. |
| Sources/LCP/License/Model/Components/LCP/User.swift | Migrates extensions storage to [String: JSONValue] and JSONValue parsing. |
| Sources/LCP/License/Model/Components/LCP/Signature.swift | Adds JSONValue-based initializer; bridges legacy initializer. |
| Sources/LCP/License/Model/Components/LCP/Rights.swift | Migrates extensions storage to [String: JSONValue] and JSONValue parsing. |
| Sources/LCP/License/Model/Components/LCP/Encryption.swift | Adds JSONValue-based initializer; bridges legacy initializer. |
| Sources/LCP/License/Model/Components/LCP/ContentKey.swift | Adds JSONValue-based initializer; bridges legacy initializer. |
| Sources/Internal/JSON.swift | Removes the old Internal JSONDictionary/parse helpers implementation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Sources/Shared/Publication/Extensions/Archive/Properties+Archive.swift
Outdated
Show resolved
Hide resolved
|
@mickael-menu I'll leave the remaining Copilot comments as unresolved in case you want to review the changes I made based on them. |
81f363e to
121bcdc
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 117 out of 117 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (4)
Sources/Shared/Toolkit/Format/Sniffers/JSONFormatSniffer.swift:1
jsonis not defined in this scope, so this closure will not compile. Return the mapped value (jsonValue) or the intended variable from the surrounding scope (if any) instead.
Tests/SharedTests/Publication/LocatorTests.swift:1XCTAssertEqualis not a throwing function, so prefixing it withtrywill fail compilation (“No throwing calls occur within 'try' expression”). Removetryfrom theXCTAssertEqual(...)call.
Sources/Shared/Publication/LinkRelation.swift:1init?(rawValue:)is failable but currently cannot fail, andinit(_:)force-unwraps it. Makeinit(rawValue:)non-failable (or avoid the force unwrap ininit(_:)) to remove an unnecessary crash path and better reflect the actual behavior.
Sources/Shared/Publication/LinkRelation.swift:1init?(rawValue:)is failable but currently cannot fail, andinit(_:)force-unwraps it. Makeinit(rawValue:)non-failable (or avoid the force unwrap ininit(_:)) to remove an unnecessary crash path and better reflect the actual behavior.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This PR does the following:
Anyor[String: Any]were updated to use JSONValue.init(json: [String: Any]?)and the like were left for convenience, but ultimately use the new init in it.Note this has breaking changes. I've drafted them in the Migration Guide.