Skip to content

Commit db47a72

Browse files
committed
Add documentation
1 parent 7126c92 commit db47a72

File tree

1 file changed

+35
-0
lines changed

1 file changed

+35
-0
lines changed

Sources/DynamicJSON/Utilities.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,21 @@
88
import Foundation
99

1010
extension String {
11+
/// Normalizes a key string into lowercase snake_case format.
12+
///
13+
/// This helps unify access to JSON keys that may use various formats such as:
14+
/// - camelCase
15+
/// - PascalCase
16+
/// - snake_case
17+
/// - kebab-case
18+
/// - Spaced strings ("Feature Toggle")
19+
///
20+
/// For example:
21+
/// - "betaFeatureX" -> "beta_feature_x"
22+
/// - "BETA-FEATURE-X" -> "beta_feature_x"
23+
/// - "Feature Toggle" -> "feature_toggle"
24+
///
25+
/// Returns: A normalized version of the string for consistent lookup.
1126
func normalizedKey() -> String {
1227
let pattern = #"(?<=[a-z0-9])(?=[A-Z])|[_\-\s]+"#
1328
let regex = try! NSRegularExpression(pattern: pattern, options: [])
@@ -21,6 +36,15 @@ extension String {
2136
.joined(separator: "_")
2237
}
2338

39+
/// Calculates the Levenshtein distance between two strings.
40+
///
41+
/// The Levenshtein distance is a measure of how many single-character edits
42+
/// (insertions, deletions, or substitutions) are required to change one word into another.
43+
///
44+
/// This is useful for implementing fuzzy string matching.
45+
///
46+
/// - Parameter target: The string to compare against.
47+
/// - Returns: The number of edits needed to match the target.
2448
func levenshteinDistance(to target: String) -> Int {
2549
let source = Array(self)
2650
let target = Array(target)
@@ -47,6 +71,17 @@ extension String {
4771
}
4872

4973
extension Dictionary where Key == String, Value == DynamicJSON {
74+
/// Attempts to find the best-matching key in the dictionary for a given lookup key.
75+
///
76+
/// Matching is performed in the following order:
77+
/// 1. Exact match (after normalization)
78+
/// 2. Partial containment (normalized query is a substring of a key)
79+
/// 3. Fuzzy match using Levenshtein distance (within a threshold)
80+
///
81+
/// - Parameters:
82+
/// - key: The original key string provided for lookup.
83+
/// - logMatch: A closure used to report fallback key matches for debugging.
84+
/// - Returns: The best matching `DynamicJSON` value, or `nil` if no reasonable match found.
5085
func fuzzyMatch(for key: String, logMatch: (_ original: String, _ matched: String) -> Void) -> DynamicJSON? {
5186
let normalized = key.normalizedKey()
5287

0 commit comments

Comments
 (0)