La risposta facile alla tua domanda è: convertire la stringa JSON restituita in un oggetto Dizionario. Qualcosa di simile a questo:
let data = jsonDataItem.dataUsingEncoding(NSUTF8StringEncoding)
if data != nil {
var error : NSError?
let dict = NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments, error: &error) as? NSDictionary
if let e = error {
...
} else {
...
}
Tuttavia, vorrei vivamente di guardare il più alto livello di DynamoDB classe mapper Quando si utilizza DynamoDB classe mapper, è possibile definire la struttura dei dati, e solo dare a DynamoDB Mapper. Ecco un esempio completo, dalla creazione della tabella alla cancellazione della tabella. L'esempio inserisce, rimuove, scansiona e interroga la tabella utilizzando DynamoDB Mapper.
In primo luogo, è necessario inizializzare l'SDK client
let cp = AWSStaticCredentialsProvider(accessKey: "AK...", secretKey: "xxx")
let configuration = AWSServiceConfiguration(region: AWSRegionType.USEast1, credentialsProvider: cp)
AWSServiceManager.defaultServiceManager().setDefaultServiceConfiguration(configuration)
Questo è solo un esempio. Non è una buona pratica incorporare una chiave di accesso e una chiave segreta nel codice. La migliore pratica sarebbe quella di utilizzare lo AWSCognitoCredentialsProvider invece (read more about Cognito).
Definire una classe che mappa i tuoi articoli nella tabella
class Item : AWSDynamoDBModel, AWSDynamoDBModeling {
var email : String = ""
var date : String = ""
var note : String = ""
var number : Double = 0.0
override init!() { super.init() }
required init!(coder: NSCoder!) {
fatalError("init(coder:) has not been implemented")
}
class func dynamoDBTableName() -> String! {
return "Demo"
}
class func hashKeyAttribute() -> String! {
return "email"
}
class func rangeKeyAttribute() -> String! {
return "date"
}
//required to let DynamoDB Mapper create instances of this class
override init(dictionary dictionaryValue: [NSObject : AnyObject]!, error: NSErrorPointer) {
super.init(dictionary: dictionaryValue, error: error)
}
//workaround to possible XCode 6.1 Bug : "Type NotificationAck" does not conform to protocol "NSObjectProtocol"
override func isEqual(anObject: AnyObject?) -> Bool {
return super.isEqual(anObject)
} }
per creare una tabella
self.createTable().continueWithSuccessBlock {(task: BFTask!) -> BFTask! in
NSLog("Create table - success")
return nil
}
func createTable() -> BFTask! {
let pt = AWSDynamoDBProvisionedThroughput()
pt.readCapacityUnits = 10
pt.writeCapacityUnits = 10
let emailAttr = AWSDynamoDBAttributeDefinition()
emailAttr.attributeName = "email"
emailAttr.attributeType = AWSDynamoDBScalarAttributeType.S
let dateAttr = AWSDynamoDBAttributeDefinition()
dateAttr.attributeName = "date"
dateAttr.attributeType = AWSDynamoDBScalarAttributeType.S
let emailKey = AWSDynamoDBKeySchemaElement()
emailKey.attributeName = "email"
emailKey.keyType = AWSDynamoDBKeyType.Hash
let dateKey = AWSDynamoDBKeySchemaElement()
dateKey.attributeName = "date"
dateKey.keyType = AWSDynamoDBKeyType.Range
let ct = AWSDynamoDBCreateTableInput()
ct.tableName = "Demo"
ct.provisionedThroughput = pt
ct.attributeDefinitions = [emailAttr, dateAttr]
ct.keySchema = [ emailKey, dateKey ]
NSLog("Creating table")
let client = AWSDynamoDB.defaultDynamoDB()
return client.createTable(ct)
}
per eliminare una tabella
self.deleteTable().continueWithSuccessBlock({ (task: BFTask!) -> BFTask! in
NSLog("Delete table - success")
return nil
})
func deleteTable() -> BFTask! {
let dt = AWSDynamoDBDeleteTableInput()
dt.tableName = "Demo"
NSLog("Deleting table")
let client = AWSDynamoDB.defaultDynamoDB()
return client.deleteTable(dt)
}
.210
Per inserire elementi
self.insertSomeItems().continueWithBlock({
(task: BFTask!) -> BFTask! in
if (task.error != nil) {
NSLog(task.error.description)
} else {
NSLog("DynamoDB save succeeded")
}
return nil;
})
func insertSomeItems() -> BFTask! {
let mapper = AWSDynamoDBObjectMapper.defaultDynamoDBObjectMapper()
var item = Item()
item.email = "[email protected]"
item.date = "20141101"
item.note = "This is item #1"
item.number = 1.0
let task1 = mapper.save(item)
item = Item()
item.email = "[email protected]"
item.date = "20141102"
item.note = "This is item #2"
item.number = 2.0
let task2 = mapper.save(item)
item = Item()
item.email = "[email protected]"
item.date = "20141103"
item.note = "This is item #3"
item.number = 3.0
let task3 = mapper.save(item)
return BFTask(forCompletionOfAllTasks: [task1, task2, task3])
}
Per caricare un singolo elemento
self.load("[email protected]", range:"20141101").continueWithSuccessBlock({ (task: BFTask!) -> BFTask! in
NSLog("Load one value - success")
let item = task.result as Item
print(item)
return nil
})
func load(hash: String, range: String) -> BFTask! {
let mapper = AWSDynamoDBObjectMapper.defaultDynamoDBObjectMapper()
return mapper.load(Item.self, hashKey: hash, rangeKey: range)
}
Per eseguire query su hash e la gamma chiave
/*
keyConditions
http://docs.aws.amazon.com/AWSiOSSDK/latest/Classes/AWSDynamoDBQueryInput.html#//api/name/keyConditions
*/
let cond = AWSDynamoDBCondition()
let v1 = AWSDynamoDBAttributeValue(); v1.S = "20141101"
cond.comparisonOperator = AWSDynamoDBComparisonOperator.EQ
cond.attributeValueList = [ v1 ]
let c = [ "date" : cond ]
self.query("[email protected]", keyConditions:c).continueWithSuccessBlock({ (task: BFTask!) -> BFTask! in
NSLog("Query multiple values - success")
let results = task.result as AWSDynamoDBPaginatedOutput
for r in results.items {
print(r)
}
return nil
})
func query(hash: String, keyConditions:[NSObject:AnyObject]) -> BFTask! {
let mapper = AWSDynamoDBObjectMapper.defaultDynamoDBObjectMapper()
let exp = AWSDynamoDBQueryExpression()
exp.hashKeyValues = hash
exp.rangeKeyConditions = keyConditions
return mapper.query(Item.self, expression: exp)
}
Per eseguire la scansione articoli (completo scansione tabella)
let cond = AWSDynamoDBCondition()
let v1 = AWSDynamoDBAttributeValue(); v1.S = "20141101"
cond.comparisonOperator = AWSDynamoDBComparisonOperator.GT
cond.attributeValueList = [ v1 ]
let exp = AWSDynamoDBScanExpression()
exp.scanFilter = [ "date" : cond ]
self.scan(exp).continueWithSuccessBlock({ (task: BFTask!) -> BFTask! in
NSLog("Scan multiple values - success")
let results = task.result as AWSDynamoDBPaginatedOutput
for r in results.items {
print(r)
}
return nil
})
func scan(expression : AWSDynamoDBScanExpression) -> BFTask! {
let mapper = AWSDynamoDBObjectMapper.defaultDynamoDBObjectMapper()
return mapper.scan(Item.self, expression: expression)
}
Se non avete altro uso DynamoDB negli Stati Uniti EST 1, non v'è alcun costo associato a eseguire questo esempio, come si sta cadendo in DynamoDB's free tier.
Grazie per la risposta. Ho provato entrambi i metodi e non sono riuscito a ottenere il risultato che sto cercando. Il primo sembra fallire perché il JSON restituito non è in realtà un JSON correttamente formato. Mi piacerebbe far funzionare l'oggetto mapper se possibile, sai come funzionerebbe se l'azione fosse "query" invece di "salva"? Per essere chiari mi piacerebbe interrogare la tabella degli utenti usando il campo userid - questo non è l'indice primario, è un indice secondario - e vorrei recuperare l''area' per questo utente. – ollym
Sì, è possibile eseguire query utilizzando anche il mapper. Vedi http://docs.aws.amazon.com/AWSiOSSDK/latest/Classes/AWSDynamoDBObjectMapper.html#//api/name/query:expression: cercherò di farti un esempio se avessi tempo stasera –
Ho provato questo alcune volte e senza fortuna! Pensi di poter mostrare un semplice esempio? Incollo ciò che ho già fatto quando torno alla mia macchina di sviluppo ... – ollym