Repository navigation
v2.4.0
JSONValue— aHashable/Sendable/CodableJSON value enum (string/number/int/bool/array/object/null), created from any property-styleSendablevalue. Numbers are normalized (integral3.0→.int(3)), so values compare and hash consistently across producers. Integers beyondInt.maxfall back to.number(documented 2^53 precision caveat). Prior art: turf-swift'sJSONValue, GEOSwift'sJSON.Feature.properties(as:decoder:)/GeoJson.foreignMembers(as:decoder:)— decode properties into anyDecodabletype. Values are converted toJSONValue, encoded to JSON, and decoded with the givenJSONDecoder, soCodingKeys,dateDecodingStrategy,keyDecodingStrategy, … work and realDecodingErrors are thrown instead of failing silently. The normalization fixes the3.0→Intsharp edge from the issue.Feature(encodedProperties:)— create aFeaturefromEncodableproperties; values are stored as nativeSendablevalues (IntstaysInt). Non-object roots throw.jsonValue(for:)/jsonForeignMember(for:)—JSONValueaccessors for exhaustive pattern matching.jsonProperties()/jsonForeignMembers()— bulk conversion of all properties / foreign members into[String: JSONValue](direct conversion, no JSON round-trip, numbers normalized along the way).JSONValueextensions — typed accessors (stringValue,intValue(.number(3.0)reads as3),doubleValue(.int(3)reads as3.0),boolValue,arrayValue,objectValue,isNull), chainable subscripts (value["a"]?["b"]?[0]), coercion accessors (coercedIntValueetc., also accepting"3"-style strings),ExpressibleBy*Literalconformances (let v: JSONValue = ["a": [1, 2.5, true]]),asJsonData/asJsonString(prettyPrinted:),init?(jsonData:)/init?(jsonString:), anddescriptionrendering compact JSON.JSONValuecustom==/hash(into:)— an integer and a number compare equal when the number is exactly that integer (.int(3) == .number(3.0), hashing equal, deduplicating in sets); same-case comparisons remain exact. Mirrors the parsing normalization but applies to directly-constructed values, too.intValue/doubleValue/boolValue/stringValue(ForeignMember) — coercing scalar accessors (feature.intValue(for: "priority")succeeds on a stored3.0; booleans are never converted to numbers, using the sameobjCTypediscriminator asJsonCoercion).HashableforPoint,MultiPoint,LineString,MultiLineString,GeometryCollection,Feature, andFeatureCollection— explicithash(into:)implementations consistent with each type's==(never synthesized, since cachedboundingBox/foreignMembersare not part of==).
Compatibility
100% backwards compatible:
- New API only; the stored
propertiestype, existing accessors (property(for:),subscript,foreignMember(for:)), and all==implementations are unchanged.