Started to work on the perl search request
This commit is contained in:
@@ -45,23 +45,40 @@ public class OpenFoodFactsClient {
|
||||
public let purchasePlacesTags: String?
|
||||
}
|
||||
|
||||
public func search(_ productName: String, queryParams: SearchQuery? = nil) async throws -> SearchResponse {
|
||||
let qp = Mirror(reflecting: queryParams ?? {})
|
||||
var s: String = "?product_name=\(productName)&"
|
||||
for case let (label?, value) in qp.children {
|
||||
s += label.camelCaseToSnakeCase() + "=" + (value as! String) + "&"
|
||||
}
|
||||
guard let endpoint = baseURL?.appendingPathComponent("search\(s)") else { throw OFFError.invalidURL }
|
||||
var request = URLRequest(url: endpoint)
|
||||
request.setValue("application/json", forHTTPHeaderField: "accept")
|
||||
// public func search(_ productName: String, queryParams: SearchQuery? = nil) async throws -> SearchResponse {
|
||||
// let qp = Mirror(reflecting: queryParams ?? {})
|
||||
// var s: String = "?product_name=\(productName)&"
|
||||
// for case let (label?, value) in qp.children {
|
||||
// s += label.camelCaseToSnakeCase() + "=" + (value as! String) + "&"
|
||||
// }
|
||||
// guard let endpoint = baseURL?.appendingPathComponent("search\(s)") else { throw OFFError.invalidURL }
|
||||
// var request = URLRequest(url: endpoint)
|
||||
// request.setValue("application/json", forHTTPHeaderField: "accept")
|
||||
|
||||
// let (data, response) = try await URLSession.shared.data(for: request)
|
||||
// guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
|
||||
// throw OFFError.invalidResponse
|
||||
// }
|
||||
// do {
|
||||
// return try JSONDecoder().decode(SearchResponse.self, from: data)
|
||||
// }
|
||||
// }
|
||||
|
||||
//https://wiki.openfoodfacts.org/API/Read/Search#Parameters
|
||||
public func search(query: PerlSearchQuery) async throws -> SearchResponse {
|
||||
let endpoint = URL(string: "https://world.openfoodfacts.org/cgi/search.pl?\(query.makeToRequest())")!
|
||||
print(endpoint)
|
||||
let request = URLRequest(url: endpoint)
|
||||
// request.setValue("application/json", forHTTPHeaderField: "accept")
|
||||
let (data, response) = try await URLSession.shared.data(for: request)
|
||||
|
||||
guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
|
||||
throw OFFError.invalidResponse
|
||||
}
|
||||
do {
|
||||
return try JSONDecoder().decode(SearchResponse.self, from: data)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ public struct Ingredient: Codable, ObjectDebugger {
|
||||
public var id: String? = nil
|
||||
public var origin: String? = nil
|
||||
public var percent: Float? = nil
|
||||
public var rank: Int? = 0
|
||||
public var rank: Float? = 0
|
||||
public var text: String? = nil
|
||||
public var vegan: String? = nil
|
||||
public var vegetarian: String? = nil
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
public struct LanguagesCodes: Codable, ObjectDebugger {
|
||||
public var en: Int? = nil
|
||||
public var fr: Int? = nil
|
||||
public var pl: Int? = nil
|
||||
public var en: Float? = nil
|
||||
public var fr: Float? = nil
|
||||
public var pl: Float? = nil
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ public struct Nutriments: Codable, ObjectDebugger {
|
||||
public var energy100G: Float? = 0
|
||||
public var energyKcal100G: Float? = 0
|
||||
public var energyKj100G: Float? = 0
|
||||
public var energyServing: Int? = 0
|
||||
public var energyServing: Float? = 0
|
||||
public var energyKcalServing: Double? = 0.0
|
||||
public var energyKjServing: Float? = 0
|
||||
public var energyUnit: String? = nil
|
||||
@@ -115,12 +115,6 @@ public struct Nutriments: Codable, ObjectDebugger {
|
||||
public var vitaminDServing: Float? = 0.0
|
||||
public var vitaminDUnit: String? = nil
|
||||
|
||||
// public var other: [String: Any] = [:]
|
||||
//
|
||||
// mutating func setDetail(key: String, value: Any) {
|
||||
// other[key] = value
|
||||
// }
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case calcium
|
||||
case calciumValue = "calcium_value"
|
||||
|
||||
48
Sources/OpenFoodFacts/types/PerlSearchQuery.swift
Normal file
48
Sources/OpenFoodFacts/types/PerlSearchQuery.swift
Normal file
@@ -0,0 +1,48 @@
|
||||
public enum PerlOperator: String {
|
||||
case lt, lte, gt, gte, eq
|
||||
}
|
||||
|
||||
public enum PerlFormat: String {
|
||||
case json, xml, jqm
|
||||
}
|
||||
|
||||
public struct SearchNutrimentEntry {
|
||||
public let nutriment: SearchNutriment
|
||||
public let op: PerlOperator
|
||||
public let value: Int
|
||||
}
|
||||
|
||||
public struct SearchTagsEntry {
|
||||
public let tag: SearchTag
|
||||
public let value: String
|
||||
public let contains: Bool = true
|
||||
}
|
||||
|
||||
//https://wiki.openfoodfacts.org/API/Read/Search#Parameters
|
||||
public struct PerlSearchQuery {
|
||||
public var searchTerms: String
|
||||
public var searchTags: [SearchTagsEntry]? // tagtype_i=SearchTag — i as #element (starting from 0); (tag_contains_i|tag_does_not_contain_i)=String
|
||||
public var searchNutriment: [SearchNutrimentEntry]? // nutriment_i=SearchNutriment — i as #element (starting from 0); nutriment_compare_i=PerlOperator; nutriment_value_i=String
|
||||
public var page: Int = 1 // Pagination
|
||||
public var format: PerlFormat // json=1 | xml=1 | jqm=1
|
||||
|
||||
public func makeToRequest() -> String {
|
||||
var _searchTags: String?
|
||||
var _searchNutriment: String?
|
||||
let _format: String = "\(format.rawValue)=1"
|
||||
let _page: String = "page=\(page)"
|
||||
if let tags = searchTags {
|
||||
_searchTags = tags.enumerated().map { i, v in
|
||||
return "tagtype_\(i)=\(v.tag.rawValue)&tag_contains_\(i)=\(v.contains ? "contains" : "does_not_contain")&tag_\(i)=\(v.value)"
|
||||
}.joined(separator: "&")
|
||||
}
|
||||
if let nutriments = searchNutriment {
|
||||
_searchNutriment = nutriments.enumerated().map { i, v in
|
||||
return "nutriment_\(i)=\(v.nutriment.rawValue)&nutriment_compare_\(i)=\(v.op.rawValue)&nutriment_value_\(i)=\(v.nutriment.rawValue)"
|
||||
}.joined(separator: "&")
|
||||
}
|
||||
|
||||
return "search_terms=\(searchTerms)\(_searchTags != nil ? "&\(_searchTags!)" : "")\(_searchNutriment != nil ? "&\(_searchNutriment!)" : "")&\(_page)&\(_format)"
|
||||
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,8 @@ public class Product: Codable, ObjectDebugger {
|
||||
public var nutriments: Nutriments? = Nutriments()
|
||||
public var selectedImages: SelectedImages?
|
||||
public var sources: [Source]? = []
|
||||
public var additivesN: Int?
|
||||
public var additivesOldN: Int?
|
||||
public var additivesN: Float?
|
||||
public var additivesOldN: Float?
|
||||
public var additivesOriginalTags: [String]?
|
||||
public var additivesOldTags: [String]?
|
||||
public var additivesPrevOriginalTags: [String]?
|
||||
@@ -36,8 +36,8 @@ public class Product: Codable, ObjectDebugger {
|
||||
public var code: String?
|
||||
public var codesTags: [String]?
|
||||
public var comparedToCategory: String?
|
||||
public var complete: Int?
|
||||
public var completedT: Int?
|
||||
public var complete: Float?
|
||||
public var completedT: Float?
|
||||
public var completeness: Double?
|
||||
public var conservationConditions: String?
|
||||
public var countries: String?
|
||||
@@ -46,7 +46,7 @@ public class Product: Codable, ObjectDebugger {
|
||||
public var countriesDebugTags: [String]?
|
||||
public var countriesTags: [String]?
|
||||
public var correctorsTags: [String]?
|
||||
public var createdT: Int?
|
||||
public var createdT: Float?
|
||||
public var creator: String?
|
||||
public var dataQualityBugsTags: [String]?
|
||||
public var dataQualityErrorsTags: [String]?
|
||||
@@ -64,7 +64,7 @@ public class Product: Codable, ObjectDebugger {
|
||||
public var entryDatesTags: [String]?
|
||||
public var expirationDate: String?
|
||||
public var expirationDateDebugTags: [String]?
|
||||
public var fruitsVegetablesNuts100GEstimate: Int?
|
||||
public var fruitsVegetablesNuts100GEstimate: Float?
|
||||
public var genericName: String?
|
||||
public var id: String?
|
||||
public var imageFrontSmallUrl: String?
|
||||
@@ -82,24 +82,24 @@ public class Product: Codable, ObjectDebugger {
|
||||
public var informersTags: [String]?
|
||||
public var ingredientsAnalysisTags: [String]?
|
||||
public var ingredientsDebug: [String?]?
|
||||
public var ingredientsFromOrThatMayBeFromPalmOilN: Int?
|
||||
public var ingredientsFromOrThatMayBeFromPalmOilN: Float?
|
||||
public var ingredientsFromPalmOilTags: [String]?
|
||||
public var ingredientsFromPalmOilN: Int?
|
||||
public var ingredientsFromPalmOilN: Float?
|
||||
public var ingredientsHierarchy: [String]?
|
||||
public var ingredientsIdsDebug: [String]?
|
||||
public var ingredientsN: Int?
|
||||
public var ingredientsN: Float?
|
||||
public var ingredientsNTags: [String]?
|
||||
public var ingredientsOriginalTags: [String]?
|
||||
public var ingredientsTags: [String]?
|
||||
public var ingredientsText: String?
|
||||
public var ingredientsTextDebug: String?
|
||||
public var ingredientsTextWithAllergens: String?
|
||||
public var ingredientsThatMayBeFromPalmOilN: Int?
|
||||
public var ingredientsThatMayBeFromPalmOilN: Float?
|
||||
public var ingredientsThatMayBeFromPalmOilTags: [String]?
|
||||
public var interfaceVersionCreated: String?
|
||||
public var interfaceVersionModified: String?
|
||||
public var keywords: [String]?
|
||||
public var knownIngredientsN: Int?
|
||||
public var knownIngredientsN: Float?
|
||||
public var labels: String?
|
||||
public var labelsHierarchy: [String]?
|
||||
public var labelsLc: String?
|
||||
@@ -114,9 +114,9 @@ public class Product: Codable, ObjectDebugger {
|
||||
public var lastEditDatesTags: [String]?
|
||||
public var lastEditor: String?
|
||||
public var lastImageDatesTags: [String]?
|
||||
public var lastImageT: Int?
|
||||
public var lastImageT: Float?
|
||||
public var lastModifiedBy: String?
|
||||
public var lastModifiedT: Int?
|
||||
public var lastModifiedT: Float?
|
||||
public var lc: String?
|
||||
public var link: String?
|
||||
public var linkDebugTags: [String]?
|
||||
@@ -130,9 +130,9 @@ public class Product: Codable, ObjectDebugger {
|
||||
public var netWeightUnit: String?
|
||||
public var netWeightValue: String?
|
||||
public var nutritionDataPer: String?
|
||||
public var nutritionScoreWarningNoFruitsVegetablesNuts: Int?
|
||||
public var nutritionScoreWarningNoFruitsVegetablesNuts: Float?
|
||||
public var noNutritionData: String?
|
||||
public var novaGroup: Int?
|
||||
public var novaGroup: Float?
|
||||
public var novaGroups: String?
|
||||
public var novaGroupDebug: String?
|
||||
public var novaGroupTags: [String]?
|
||||
@@ -145,9 +145,9 @@ public class Product: Codable, ObjectDebugger {
|
||||
public var nutritionDataPrepared: String?
|
||||
public var nutritionDataPreparedPer: String?
|
||||
public var nutritionGrades: String?
|
||||
public var nutritionScoreBeverage: Int?
|
||||
public var nutritionScoreBeverage: Float?
|
||||
public var nutritionScoreDebug: String?
|
||||
public var nutritionScoreWarningNoFiber: Int?
|
||||
public var nutritionScoreWarningNoFiber: Float?
|
||||
public var nutritionGradesTags: [String]?
|
||||
public var origins: String?
|
||||
public var originsDebugTags: [String]?
|
||||
@@ -162,7 +162,7 @@ public class Product: Codable, ObjectDebugger {
|
||||
public var pnnsGroups2: String?
|
||||
public var pnnsGroups1Tags: [String]?
|
||||
public var pnnsGroups2Tags: [String]?
|
||||
public var popularityKey: Int?
|
||||
public var popularityKey: Float?
|
||||
public var producerVersionId: String?
|
||||
public var productName: String?
|
||||
public var productQuantity: Float?
|
||||
@@ -173,11 +173,11 @@ public class Product: Codable, ObjectDebugger {
|
||||
public var quantity: String?
|
||||
public var quantityDebugTags: [String]?
|
||||
public var recyclingInstructionsToDiscard: String?
|
||||
public var rev: Int?
|
||||
public var rev: Float?
|
||||
public var servingQuantity: String?
|
||||
public var servingSize: String?
|
||||
public var servingSizeDebugTags: [String]?
|
||||
public var sortkey: Int?
|
||||
public var sortkey: Float?
|
||||
public var states: String?
|
||||
public var statesHierarchy: [String]?
|
||||
public var statesTags: [String]?
|
||||
@@ -191,7 +191,7 @@ public class Product: Codable, ObjectDebugger {
|
||||
public var tracesFromUser: String?
|
||||
public var tracesLc: String?
|
||||
public var tracesTags: [String]?
|
||||
public var unknownIngredientsN: Int?
|
||||
public var unknownIngredientsN: Float?
|
||||
public var unknownNutrientsTags: [String]?
|
||||
public var updateKey: String?
|
||||
public var vitaminsPrevTags: [String]?
|
||||
@@ -405,8 +405,8 @@ public class Product: Codable, ObjectDebugger {
|
||||
nutriments = try container.decodeIfPresent(Nutriments.self, forKey: .nutriments) ?? Nutriments()
|
||||
selectedImages = try container.decodeIfPresent(SelectedImages.self, forKey: .selectedImages)
|
||||
sources = try container.decodeIfPresent([Source].self, forKey: .sources)
|
||||
additivesN = try container.decodeIfPresent(Int.self, forKey: .additivesN)
|
||||
additivesOldN = try container.decodeIfPresent(Int.self, forKey: .additivesOldN)
|
||||
additivesN = try container.decodeIfPresent(Float.self, forKey: .additivesN)
|
||||
additivesOldN = try container.decodeIfPresent(Float.self, forKey: .additivesOldN)
|
||||
additivesOriginalTags = try container.decodeIfPresent([String].self, forKey: .additivesOriginalTags)
|
||||
additivesOldTags = try container.decodeIfPresent([String].self, forKey: .additivesOldTags)
|
||||
additivesPrevOriginalTags = try container.decodeIfPresent([String].self, forKey: .additivesPrevOriginalTags)
|
||||
@@ -435,8 +435,8 @@ public class Product: Codable, ObjectDebugger {
|
||||
code = try container.decodeIfPresent(String.self, forKey: .code)
|
||||
codesTags = try container.decodeIfPresent([String].self, forKey: .codesTags)
|
||||
comparedToCategory = try container.decodeIfPresent(String.self, forKey: .comparedToCategory)
|
||||
complete = try container.decodeIfPresent(Int.self, forKey: .complete)
|
||||
completedT = try container.decodeIfPresent(Int.self, forKey: .completedT)
|
||||
complete = try container.decodeIfPresent(Float.self, forKey: .complete)
|
||||
completedT = try container.decodeIfPresent(Float.self, forKey: .completedT)
|
||||
completeness = try container.decodeIfPresent(Double.self, forKey: .completeness)
|
||||
conservationConditions = try container.decodeIfPresent(String.self, forKey: .conservationConditions)
|
||||
countries = try container.decodeIfPresent(String.self, forKey: .countries)
|
||||
@@ -445,7 +445,7 @@ public class Product: Codable, ObjectDebugger {
|
||||
countriesDebugTags = try container.decodeIfPresent([String].self, forKey: .countriesDebugTags)
|
||||
countriesTags = try container.decodeIfPresent([String].self, forKey: .countriesTags)
|
||||
correctorsTags = try container.decodeIfPresent([String].self, forKey: .correctorsTags)
|
||||
createdT = try container.decodeIfPresent(Int.self, forKey: .createdT)
|
||||
createdT = try container.decodeIfPresent(Float.self, forKey: .createdT)
|
||||
creator = try container.decodeIfPresent(String.self, forKey: .creator)
|
||||
dataQualityBugsTags = try container.decodeIfPresent([String].self, forKey: .dataQualityBugsTags)
|
||||
dataQualityErrorsTags = try container.decodeIfPresent([String].self, forKey: .dataQualityErrorsTags)
|
||||
@@ -463,7 +463,7 @@ public class Product: Codable, ObjectDebugger {
|
||||
entryDatesTags = try container.decodeIfPresent([String].self, forKey: .entryDatesTags)
|
||||
expirationDate = try container.decodeIfPresent(String.self, forKey: .expirationDate)
|
||||
expirationDateDebugTags = try container.decodeIfPresent([String].self, forKey: .expirationDateDebugTags)
|
||||
fruitsVegetablesNuts100GEstimate = try container.decodeIfPresent(Int.self, forKey: .fruitsVegetablesNuts100GEstimate)
|
||||
fruitsVegetablesNuts100GEstimate = try container.decodeIfPresent(Float.self, forKey: .fruitsVegetablesNuts100GEstimate)
|
||||
genericName = try container.decodeIfPresent(String.self, forKey: .genericName)
|
||||
id = try container.decodeIfPresent(String.self, forKey: .id)
|
||||
imageFrontSmallUrl = try container.decodeIfPresent(String.self, forKey: .imageFrontSmallUrl)
|
||||
@@ -481,21 +481,21 @@ public class Product: Codable, ObjectDebugger {
|
||||
informersTags = try container.decodeIfPresent([String].self, forKey: .informersTags)
|
||||
ingredientsAnalysisTags = try container.decodeIfPresent([String].self, forKey: .ingredientsAnalysisTags)
|
||||
ingredientsDebug = try container.decodeIfPresent([String?].self, forKey: .ingredientsDebug)
|
||||
ingredientsFromOrThatMayBeFromPalmOilN = try container.decodeIfPresent(Int.self, forKey: .ingredientsFromOrThatMayBeFromPalmOilN)
|
||||
ingredientsFromOrThatMayBeFromPalmOilN = try container.decodeIfPresent(Float.self, forKey: .ingredientsFromOrThatMayBeFromPalmOilN)
|
||||
ingredientsFromPalmOilTags = try container.decodeIfPresent([String].self, forKey: .ingredientsFromPalmOilTags)
|
||||
ingredientsFromPalmOilN = try container.decodeIfPresent(Int.self, forKey: .ingredientsFromPalmOilN)
|
||||
ingredientsFromPalmOilN = try container.decodeIfPresent(Float.self, forKey: .ingredientsFromPalmOilN)
|
||||
ingredientsHierarchy = try container.decodeIfPresent([String].self, forKey: .ingredientsHierarchy)
|
||||
ingredientsIdsDebug = try container.decodeIfPresent([String].self, forKey: .ingredientsIdsDebug)
|
||||
if container.contains(.ingredientsN) {
|
||||
if try container.decodeNil(forKey: .ingredientsN) {
|
||||
ingredientsN = nil
|
||||
} else {
|
||||
if let intValue = try? container.decode(Int.self, forKey: .ingredientsN) {
|
||||
if let intValue = try? container.decode(Float.self, forKey: .ingredientsN) {
|
||||
ingredientsN = intValue
|
||||
} else if let stringValue = try? container.decode(String.self, forKey: .ingredientsN) {
|
||||
ingredientsN = Int(stringValue)
|
||||
ingredientsN = Float(stringValue)
|
||||
}else {
|
||||
// If decoding as both Int and String fails, handle the error accordingly
|
||||
// If decoding as both Float and String fails, handle the error accordingly
|
||||
throw DecodingError.dataCorruptedError(
|
||||
forKey: .ingredientsN,
|
||||
in: container,
|
||||
@@ -513,12 +513,12 @@ public class Product: Codable, ObjectDebugger {
|
||||
ingredientsText = try container.decodeIfPresent(String.self, forKey: .ingredientsText)
|
||||
ingredientsTextDebug = try container.decodeIfPresent(String.self, forKey: .ingredientsTextDebug)
|
||||
ingredientsTextWithAllergens = try container.decodeIfPresent(String.self, forKey: .ingredientsTextWithAllergens)
|
||||
ingredientsThatMayBeFromPalmOilN = try container.decodeIfPresent(Int.self, forKey: .ingredientsThatMayBeFromPalmOilN)
|
||||
ingredientsThatMayBeFromPalmOilN = try container.decodeIfPresent(Float.self, forKey: .ingredientsThatMayBeFromPalmOilN)
|
||||
ingredientsThatMayBeFromPalmOilTags = try container.decodeIfPresent([String].self, forKey: .ingredientsThatMayBeFromPalmOilTags)
|
||||
interfaceVersionCreated = try container.decodeIfPresent(String.self, forKey: .interfaceVersionCreated)
|
||||
interfaceVersionModified = try container.decodeIfPresent(String.self, forKey: .interfaceVersionModified)
|
||||
keywords = try container.decodeIfPresent([String].self, forKey: .keywords)
|
||||
knownIngredientsN = try container.decodeIfPresent(Int.self, forKey: .knownIngredientsN)
|
||||
knownIngredientsN = try container.decodeIfPresent(Float.self, forKey: .knownIngredientsN)
|
||||
labels = try container.decodeIfPresent(String.self, forKey: .labels)
|
||||
labelsHierarchy = try container.decodeIfPresent([String].self, forKey: .labelsHierarchy)
|
||||
labelsLc = try container.decodeIfPresent(String.self, forKey: .labelsLc)
|
||||
@@ -533,25 +533,45 @@ public class Product: Codable, ObjectDebugger {
|
||||
lastEditDatesTags = try container.decodeIfPresent([String].self, forKey: .lastEditDatesTags)
|
||||
lastEditor = try container.decodeIfPresent(String.self, forKey: .lastEditor)
|
||||
lastImageDatesTags = try container.decodeIfPresent([String].self, forKey: .lastImageDatesTags)
|
||||
lastImageT = try container.decodeIfPresent(Int.self, forKey: .lastImageT)
|
||||
lastImageT = try container.decodeIfPresent(Float.self, forKey: .lastImageT)
|
||||
lastModifiedBy = try container.decodeIfPresent(String.self, forKey: .lastModifiedBy)
|
||||
lastModifiedT = try container.decodeIfPresent(Int.self, forKey: .lastModifiedT)
|
||||
lastModifiedT = try container.decodeIfPresent(Float.self, forKey: .lastModifiedT)
|
||||
lc = try container.decodeIfPresent(String.self, forKey: .lc)
|
||||
link = try container.decodeIfPresent(String.self, forKey: .link)
|
||||
linkDebugTags = try container.decodeIfPresent([String].self, forKey: .linkDebugTags)
|
||||
manufacturingPlaces = try container.decodeIfPresent(String.self, forKey: .manufacturingPlaces)
|
||||
manufacturingPlacesDebugTags = try container.decodeIfPresent([String].self, forKey: .manufacturingPlacesDebugTags)
|
||||
manufacturingPlacesTags = try container.decodeIfPresent([String].self, forKey: .manufacturingPlacesTags)
|
||||
maxImgid = try container.decodeIfPresent(String.self, forKey: .maxImgid)
|
||||
if container.contains(.maxImgid) {
|
||||
if try container.decodeNil(forKey: .maxImgid) {
|
||||
maxImgid = nil
|
||||
} else {
|
||||
if let floatValue = try? container.decode(Float.self, forKey: .maxImgid) {
|
||||
maxImgid = "\(floatValue)"
|
||||
} else if let stringValue = try? container.decode(String.self, forKey: .maxImgid) {
|
||||
maxImgid = stringValue
|
||||
}else {
|
||||
// If decoding as both Float and String fails, handle the error accordingly
|
||||
throw DecodingError.dataCorruptedError(
|
||||
forKey: .maxImgid,
|
||||
in: container,
|
||||
debugDescription: "Unable to decode maxImgid"
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
maxImgid = nil
|
||||
}
|
||||
mineralsPrevTags = try container.decodeIfPresent([String].self, forKey: .mineralsPrevTags)
|
||||
mineralsTags = try container.decodeIfPresent([String].self, forKey: .mineralsTags)
|
||||
miscTags = try container.decodeIfPresent([String].self, forKey: .miscTags)
|
||||
netWeightUnit = try container.decodeIfPresent(String.self, forKey: .netWeightUnit)
|
||||
netWeightValue = try container.decodeIfPresent(String.self, forKey: .netWeightValue)
|
||||
nutritionDataPer = try container.decodeIfPresent(String.self, forKey: .nutritionDataPer)
|
||||
nutritionScoreWarningNoFruitsVegetablesNuts = try container.decodeIfPresent(Int.self, forKey: .nutritionScoreWarningNoFruitsVegetablesNuts)
|
||||
nutritionScoreWarningNoFruitsVegetablesNuts = try container.decodeIfPresent(Float.self, forKey: .nutritionScoreWarningNoFruitsVegetablesNuts)
|
||||
noNutritionData = try container.decodeIfPresent(String.self, forKey: .noNutritionData)
|
||||
novaGroup = try container.decodeIfPresent(Int.self, forKey: .novaGroup)
|
||||
novaGroup = try container.decodeIfPresent(Float.self, forKey: .novaGroup)
|
||||
novaGroups = try container.decodeIfPresent(String.self, forKey: .novaGroups)
|
||||
novaGroupDebug = try container.decodeIfPresent(String.self, forKey: .novaGroupDebug)
|
||||
novaGroupTags = try container.decodeIfPresent([String].self, forKey: .novaGroupTags)
|
||||
@@ -563,9 +583,9 @@ public class Product: Codable, ObjectDebugger {
|
||||
nutritionDataPrepared = try container.decodeIfPresent(String.self, forKey: .nutritionDataPrepared)
|
||||
nutritionDataPreparedPer = try container.decodeIfPresent(String.self, forKey: .nutritionDataPreparedPer)
|
||||
nutritionGrades = try container.decodeIfPresent(String.self, forKey: .nutritionGrades)
|
||||
nutritionScoreBeverage = try container.decodeIfPresent(Int.self, forKey: .nutritionScoreBeverage)
|
||||
nutritionScoreBeverage = try container.decodeIfPresent(Float.self, forKey: .nutritionScoreBeverage)
|
||||
nutritionScoreDebug = try container.decodeIfPresent(String.self, forKey: .nutritionScoreDebug)
|
||||
nutritionScoreWarningNoFiber = try container.decodeIfPresent(Int.self, forKey: .nutritionScoreWarningNoFiber)
|
||||
nutritionScoreWarningNoFiber = try container.decodeIfPresent(Float.self, forKey: .nutritionScoreWarningNoFiber)
|
||||
nutritionGradesTags = try container.decodeIfPresent([String].self, forKey: .nutritionGradesTags)
|
||||
origins = try container.decodeIfPresent(String.self, forKey: .origins)
|
||||
originsDebugTags = try container.decodeIfPresent([String].self, forKey: .originsDebugTags)
|
||||
@@ -580,7 +600,7 @@ public class Product: Codable, ObjectDebugger {
|
||||
pnnsGroups2 = try container.decodeIfPresent(String.self, forKey: .pnnsGroups2)
|
||||
pnnsGroups1Tags = try container.decodeIfPresent([String].self, forKey: .pnnsGroups1Tags)
|
||||
pnnsGroups2Tags = try container.decodeIfPresent([String].self, forKey: .pnnsGroups2Tags)
|
||||
popularityKey = try container.decodeIfPresent(Int.self, forKey: .popularityKey)
|
||||
popularityKey = try container.decodeIfPresent(Float.self, forKey: .popularityKey)
|
||||
producerVersionId = try container.decodeIfPresent(String.self, forKey: .producerVersionId)
|
||||
productName = try container.decodeIfPresent(String.self, forKey: .productName)
|
||||
purchasePlaces = try container.decodeIfPresent(String.self, forKey: .purchasePlaces)
|
||||
@@ -590,7 +610,7 @@ public class Product: Codable, ObjectDebugger {
|
||||
quantity = try container.decodeIfPresent(String.self, forKey: .quantity)
|
||||
quantityDebugTags = try container.decodeIfPresent([String].self, forKey: .quantityDebugTags)
|
||||
recyclingInstructionsToDiscard = try container.decodeIfPresent(String.self, forKey: .recyclingInstructionsToDiscard)
|
||||
rev = try container.decodeIfPresent(Int.self, forKey: .rev)
|
||||
rev = try container.decodeIfPresent(Float.self, forKey: .rev)
|
||||
if container.contains(.servingQuantity) {
|
||||
if try container.decodeNil(forKey: .servingQuantity) {
|
||||
servingQuantity = nil
|
||||
@@ -600,7 +620,7 @@ public class Product: Codable, ObjectDebugger {
|
||||
} else if let stringValue = try? container.decode(String.self, forKey: .servingQuantity) {
|
||||
servingQuantity = stringValue
|
||||
}else {
|
||||
// If decoding as both Int and String fails, handle the error accordingly
|
||||
// If decoding as both Float and String fails, handle the error accordingly
|
||||
throw DecodingError.dataCorruptedError(
|
||||
forKey: .servingQuantity,
|
||||
in: container,
|
||||
@@ -614,7 +634,7 @@ public class Product: Codable, ObjectDebugger {
|
||||
}
|
||||
servingSize = try container.decodeIfPresent(String.self, forKey: .servingSize)
|
||||
servingSizeDebugTags = try container.decodeIfPresent([String].self, forKey: .servingSizeDebugTags)
|
||||
sortkey = try container.decodeIfPresent(Int.self, forKey: .sortkey)
|
||||
sortkey = try container.decodeIfPresent(Float.self, forKey: .sortkey)
|
||||
states = try container.decodeIfPresent(String.self, forKey: .states)
|
||||
statesHierarchy = try container.decodeIfPresent([String].self, forKey: .statesHierarchy)
|
||||
statesTags = try container.decodeIfPresent([String].self, forKey: .statesTags)
|
||||
@@ -632,12 +652,12 @@ public class Product: Codable, ObjectDebugger {
|
||||
if try container.decodeNil(forKey: .unknownIngredientsN) {
|
||||
unknownIngredientsN = nil
|
||||
} else {
|
||||
if let intValue = try? container.decode(Int.self, forKey: .unknownIngredientsN) {
|
||||
if let intValue = try? container.decode(Float.self, forKey: .unknownIngredientsN) {
|
||||
unknownIngredientsN = intValue
|
||||
} else if let stringValue = try? container.decode(String.self, forKey: .unknownIngredientsN) {
|
||||
unknownIngredientsN = Int(stringValue)
|
||||
unknownIngredientsN = Float(stringValue)
|
||||
}else {
|
||||
// If decoding as both Int and String fails, handle the error accordingly
|
||||
// If decoding as both Float and String fails, handle the error accordingly
|
||||
throw DecodingError.dataCorruptedError(
|
||||
forKey: .unknownIngredientsN,
|
||||
in: container,
|
||||
@@ -659,14 +679,14 @@ public class Product: Codable, ObjectDebugger {
|
||||
if try container.decodeNil(forKey: .productQuantity) {
|
||||
productQuantity = nil
|
||||
} else {
|
||||
// Try to decode as Int
|
||||
// Try to decode as Float
|
||||
if let floatValue = try? container.decode(Float.self, forKey: .productQuantity) {
|
||||
productQuantity = floatValue
|
||||
} else if let stringValue = try? container.decode(String.self, forKey: .productQuantity) {
|
||||
// If decoding as Int fails, try to decode as String
|
||||
// If decoding as Float fails, try to decode as String
|
||||
productQuantity = Float(stringValue)
|
||||
} else {
|
||||
// If decoding as both Int and String fails, handle the error accordingly
|
||||
// If decoding as both Float and String fails, handle the error accordingly
|
||||
throw DecodingError.dataCorruptedError(
|
||||
forKey: .productQuantity,
|
||||
in: container,
|
||||
|
||||
98
Sources/OpenFoodFacts/types/SearchNutriment.swift
Normal file
98
Sources/OpenFoodFacts/types/SearchNutriment.swift
Normal file
@@ -0,0 +1,98 @@
|
||||
public enum SearchNutriment: String, Codable {
|
||||
case energy // Energy
|
||||
case energyFromFat = "energy-from-fat" // Energy from fat
|
||||
case fat // Fat
|
||||
case saturatedFat = "saturated-fat" // Saturated fat
|
||||
case butyricAcid = "butyric-acid" // Butyric acid (4:0)
|
||||
case caproicAcid = "caproic-acid" // Caproic acid (6:0)
|
||||
case caprylicAcid = "caprylic-acid" // Caprylic acid (8:0)
|
||||
case capricAcid = "capric-acid" // Capric acid (10:0)
|
||||
case lauricAcid = "lauric-acid" // Lauric acid (12:0)
|
||||
case myristicAcid = "myristic-acid" // Myristic acid (14:0)
|
||||
case palmiticAcid = "palmitic-acid" // Palmitic acid (16:0)
|
||||
case stearicAcid = "stearic-acid" // Stearic acid (18:0)
|
||||
case arachidicAcid = "arachidic-acid" // Arachidic acid (20:0)
|
||||
case behenicAcid = "behenic-acid" // Behenic acid (22:0)
|
||||
case lignocericAcid = "lignoceric-acid" // Lignoceric acid (24:0)
|
||||
case ceroticAcid = "cerotic-acid" // Cerotic acid (26:0)
|
||||
case montanicAcid = "montanic-acid" // Montanic acid (28:0)
|
||||
case melissicAcid = "melissic-acid" // Melissic acid (30:0)
|
||||
case monounsaturatedFat = "monounsaturated-fat" // Monounsaturated fat
|
||||
case polyunsaturatedFat = "polyunsaturated-fat" // Polyunsaturated fat
|
||||
case omega3Fat = "omega-3-fat" // Omega 3 fatty acids
|
||||
case alphaLinolenicAcid = "alpha-linolenic-acid" // Alpha-linolenic acid / ALA (18:3 n-3)
|
||||
case eicosapentaenoicAcid = "eicosapentaenoic-acid" // Eicosapentaenoic acid / EPA (20:5 n-3)
|
||||
case docosahexaenoicAcid = "docosahexaenoic-acid" // Docosahexaenoic acid / DHA (22:6 n-3)
|
||||
case omega6Fat = "omega-6-fat" // Omega 6 fatty acids
|
||||
case linoleicAcid = "linoleic-acid" // Linoleic acid / LA (18:2 n-6)
|
||||
case arachidonicAcid = "arachidonic-acid" // Arachidonic acid / AA / ARA (20:4 n-6)
|
||||
case gammaLinolenicAcid = "gamma-linolenic-acid" // Gamma-linolenic acid / GLA (18:3 n-6)
|
||||
case dihomoGammaLinolenicAcid = "dihomo-gamma-linolenic-acid" // Dihomo-gamma-linolenic acid / DGLA (20:3 n-6)
|
||||
case omega9Fat = "omega-9-fat" // Omega 9 fatty acids
|
||||
case oleicAcid = "oleic-acid" // Oleic acid (18:1 n-9)
|
||||
case elaidicAcid = "elaidic-acid" // Elaidic acid (18:1 n-9)
|
||||
case gondoicAcid = "gondoic-acid" // Gondoic acid (20:1 n-9)
|
||||
case meadAcid = "mead-acid" // Mead acid (20:3 n-9)
|
||||
case erucicAcid = "erucic-acid" // Erucic acid (22:1 n-9)
|
||||
case nervonicAcid = "nervonic-acid" // Nervonic acid (24:1 n-9)
|
||||
case transFat = "trans-fat" // Trans fat
|
||||
case cholesterol // Cholesterol
|
||||
case carbohydrates // Carbohydrate
|
||||
case sugars // Sugars
|
||||
case sucrose // Sucrose
|
||||
case glucose // Glucose
|
||||
case fructose // Fructose
|
||||
case lactose // Lactose
|
||||
case maltose // Maltose
|
||||
case maltodextrins // Maltodextrins
|
||||
case starch // Starch
|
||||
case polyols // Sugar alcohols (Polyols)
|
||||
case fiber // Dietary fiber
|
||||
case proteins // Proteins
|
||||
case casein // Casein
|
||||
case serumProteins = "serum-proteins" // Serum proteins
|
||||
case nucleotides // Nucleotides
|
||||
case salt // Salt
|
||||
case sodium // Sodium
|
||||
case alcohol // Alcohol
|
||||
case vitaminA = "vitamin-a" // Vitamin A
|
||||
case betaCarotene = "beta-carotene" // Beta carotene
|
||||
case vitaminD = "vitamin-d" // Vitamin D
|
||||
case vitaminE = "vitamin-e" // Vitamin E
|
||||
case vitaminK = "vitamin-k" // Vitamin K
|
||||
case vitaminC = "vitamin-c" // Vitamin C (ascorbic acid)
|
||||
case vitaminB1 = "vitamin-b1" // Vitamin B1 (Thiamin)
|
||||
case vitaminB2 = "vitamin-b2" // Vitamin B2 (Riboflavin)
|
||||
case vitaminPP = "vitamin-pp" // Vitamin B3 / Vitamin PP (Niacin)
|
||||
case vitaminB6 = "vitamin-b6" // Vitamin B6 (Pyridoxin)
|
||||
case vitaminB9 = "vitamin-b9" // Vitamin B9 (Folic acid / Folates)
|
||||
case vitaminB12 = "vitamin-b12" // Vitamin B12 (Cobalamin)
|
||||
case biotin // Biotin
|
||||
case pantothenicAcid = "pantothenic-acid" // Pantothenic acid / Pantothenate (Vitamin B5)
|
||||
case silica // Silica
|
||||
case bicarbonate // Bicarbonate
|
||||
case potassium // Potassium
|
||||
case chloride // Chloride
|
||||
case calcium // Calcium
|
||||
case phosphorus // Phosphorus
|
||||
case iron // Iron
|
||||
case magnesium // Magnesium
|
||||
case zinc // Zinc
|
||||
case copper // Copper
|
||||
case manganese // Manganese
|
||||
case fluoride // Fluoride
|
||||
case selenium // Selenium
|
||||
case chromium // Chromium
|
||||
case molybdenum // Molybdenum
|
||||
case iodine // Iodine
|
||||
case caffeine // Caffeine
|
||||
case taurine // Taurine
|
||||
case pH // pH
|
||||
case fruitsVegetablesNuts = "fruits-vegetables-nuts" // Fruits, vegetables, and nuts (minimum)
|
||||
case collagenMeatProteinRatio = "collagen-meat-protein-ratio" // Collagen/Meat protein ratio (maximum)
|
||||
case cocoa // Cocoa (minimum)
|
||||
case chlorophyll = "chlorophyll" // Chlorophyll
|
||||
case carbonFootprint = "carbon-footprint" // Carbon footprint / CO2 emissions
|
||||
case nutritionScoreFR = "nutrition-score-fr" // Experimental nutrition score
|
||||
case nutritionScoreUK = "nutrition-score-uk" // Nutrition score - UK
|
||||
}
|
||||
17
Sources/OpenFoodFacts/types/SearchTag.swift
Normal file
17
Sources/OpenFoodFacts/types/SearchTag.swift
Normal file
@@ -0,0 +1,17 @@
|
||||
public enum SearchTag: String, Codable {
|
||||
case brands // Brands
|
||||
case categories // Categories
|
||||
case packaging // Packaging
|
||||
case labels // Labels
|
||||
case origins // Origins of ingredients
|
||||
case manufacturingPlaces = "manufacturing_places" // Manufacturing or processing places
|
||||
case embCodes = "emb_codes" // Packager codes
|
||||
case purchasePlaces = "purchase_places" // Purchase places
|
||||
case stores // Stores
|
||||
case countries // Countries
|
||||
case additives // Additives
|
||||
case allergens // Allergens
|
||||
case traces // Traces
|
||||
case nutritionGrades = "nutrition_grades" // Nutrition grades
|
||||
case states // States
|
||||
}
|
||||
@@ -4,10 +4,10 @@ import OpenFoodFacts
|
||||
let off = OpenFoodFactsClient()
|
||||
off.prod = true
|
||||
|
||||
do {
|
||||
// do {
|
||||
|
||||
let res = try await off.search("Coca-Cola")
|
||||
print(res)
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
// // let res = try await off.search("Coca-Cola")
|
||||
// // print(res)
|
||||
// } catch {
|
||||
// print(error)
|
||||
// }
|
||||
|
||||
@@ -14,4 +14,18 @@ final class swift_openfoodfacts_sdkTests: XCTestCase {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testPerlSearch() async throws {
|
||||
let off = OpenFoodFactsClient()
|
||||
do {
|
||||
// try await off.search(query: .init(searchTerms: "prince", format: .json))
|
||||
let _ = try await off.search(query: .init(
|
||||
searchTerms: "",
|
||||
searchTags: [.init(tag: .brands, value: "mondelez"), .init(tag: .countries, value: "france")],
|
||||
format: .json
|
||||
))
|
||||
} catch {
|
||||
XCTFail("\(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user