I found your unanswered question today, and kept looking until I found an answer. Probably too late for you but may help others.
aws dynamodb create-table --cli-input-json file://tabledefinition.json
This command expects a json object in the file in the format outlined by the following command:
aws dynamodb create-table --generate-cli-skeleton
This approach seems to work with many aws commands.
Answer from Keith Branton on Stack OverflowWrite a JSON File as a DynamoDB Table Item - AWS - HashiCorp Discuss
Creating Amazon DynamoDB Table Items from a JSON File - Stack Overflow
java - Create dynamodb table from JSON - Stack Overflow
Exporting Spark dataframe to AWS DynamoDB?
I found your unanswered question today, and kept looking until I found an answer. Probably too late for you but may help others.
aws dynamodb create-table --cli-input-json file://tabledefinition.json
This command expects a json object in the file in the format outlined by the following command:
aws dynamodb create-table --generate-cli-skeleton
This approach seems to work with many aws commands.
I wrote a Python script for this. My version is for yaml, but can easily be adapted to json.
Single dependency for parsing the template, with thanks to this SO post
pip install cfn_flip
#!/usr/bin/env python
import subprocess
import time
import yaml
from cfn_tools import load_yaml, dump_yaml
template_file = open('./template.yaml')
template = load_yaml(template_file.read())
for resource_key in template["Resources"]:
resource = template["Resources"][resource_key]
if resource["Type"] != 'AWS::DynamoDB::Table':
continue
table_name = resource["Properties"]["TableName"]
print(f'Creating table "{table_name}"')
table_definition = template["Resources"][resource_key]["Properties"]
time_to_live_definition = table_definition.get("TimeToLiveSpecification")
if time_to_live_definition:
# TimeToLiveSpecification is not accepted by create-table, it is a separate command
del(table_definition["TimeToLiveSpecification"])
subprocess.run(["aws", "dynamodb", "create-table", "--cli-input-yaml",dump_yaml(table_definition)])
if time_to_live_definition:
time_to_live_definition = {
"TableName": table_name,
"TimeToLiveSpecification": time_to_live_definition
}
subprocess.run(["aws", "dynamodb", "update-time-to-live", "--cli-input-yaml", dump_yaml(time_to_live_definition)])
# Tables are created asynch, give some time to complete
time.sleep(1)
The sleep at the end is for following warning mentioned in the help of create-table. I have only tested this locally so far, so a smarter way to wait for completion might be needed.
You can optionally define secondary indexes on the new table, as part of the "CreateTable" operation. If you want to create multiple tables with secondary indexes on them, you must create the tables sequentially. Only one table with secondary indexes can be in the "CREATING" state at any given time.
I was also trying to achieve something similar but I didn't find any lib for that purpose, hence I took a few minutes to code it myself.
Provided with a json file structured the same way as in the documentation example:
{
TableName : "Music",
KeySchema: [
{
AttributeName: "Artist",
KeyType: "HASH",
},
{
AttributeName: "SongTitle",
KeyType: "RANGE"
}
],
AttributeDefinitions: [
{
AttributeName: "Artist",
AttributeType: "S"
},
{
AttributeName: "SongTitle",
AttributeType: "S"
}
],
ProvisionedThroughput: {
ReadCapacityUnits: 1,
WriteCapacityUnits: 1
}
}
The code bellow works. Note that:
- The createTable method expects a json string, which you can obtain using something like
Files.readString(Path.of("path/to/your/file.json")) - if you do not use Lombok you have to create constructors/getters/setters yourself
- the
@JsonPropertyannotations are only necessary if the class field names are not an exact match to the json ones (in this case, the first letter is uppercase), explained here.
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.model.*;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@RequiredArgsConstructor
public class CreateTable {
private final AmazonDynamoDB amazonDynamoDB;
public void createTable(String json) throws JsonProcessingException {
Table table = readTable(json);
amazonDynamoDB.createTable(getTableRequest(table));
}
private CreateTableRequest getTableRequest(Table table) {
return new CreateTableRequest()
.withTableName(table.getTableName())
.withKeySchema(toKeySchemaElement(table.getKeySchema()))
.withAttributeDefinitions(toAttributeDefinition(table.getAttributeDefinitions()))
.withProvisionedThroughput(toProvisionedThroughput(table.getProvisionedThroughput()));
}
private Table readTable(String json) throws JsonProcessingException {
return new ObjectMapper().readValue(json, Table.class);
}
private ProvisionedThroughput toProvisionedThroughput(ProvisionedTp provisionedTp) {
log.info("creating provisioned throughput read: {} write: {}", provisionedTp.getReadCapacityUnits(), provisionedTp.getWriteCapacityUnits());
return new ProvisionedThroughput(provisionedTp.getReadCapacityUnits(), provisionedTp.getWriteCapacityUnits());
}
private Collection<AttributeDefinition> toAttributeDefinition(Collection<AttributeDef> attributeDefs) {
return attributeDefs.stream().map(this::toAttributeDefinition).collect(Collectors.toList());
}
private AttributeDefinition toAttributeDefinition(AttributeDef attributeDef) {
log.info("creating new attribute definition {}: {}", attributeDef.getAttributeName(), attributeDef.getAttributeType());
return new AttributeDefinition().withAttributeName(attributeDef.getAttributeName()).withAttributeType(attributeDef.getAttributeType());
}
private Collection<KeySchemaElement> toKeySchemaElement(Collection<KeySchema> keySchemas) {
return keySchemas.stream().map(this::toKeySchemaElement).collect(Collectors.toList());
}
private KeySchemaElement toKeySchemaElement(KeySchema keySchema) {
log.info("creating new key schema element {}: {}", keySchema.getAttributeName(), keySchema.getKeyType());
return new KeySchemaElement().withAttributeName(keySchema.getAttributeName()).withKeyType(keySchema.getKeyType());
}
@Data
@NoArgsConstructor
public static class Table {
@JsonProperty("TableName")
private String tableName;
@JsonProperty("KeySchema")
private List<KeySchema> keySchema;
@JsonProperty("AttributeDefinitions")
private List<AttributeDef> attributeDefinitions;
@JsonProperty("ProvisionedThroughput")
private ProvisionedTp provisionedThroughput;
}
@Data
@NoArgsConstructor
public static class KeySchema {
@JsonProperty("AttributeName")
private String attributeName;
@JsonProperty("KeyType")
private String keyType;
}
@Data
@NoArgsConstructor
public static class AttributeDef {
@JsonProperty("AttributeName")
private String attributeName;
@JsonProperty("AttributeType")
private String attributeType;
}
@Data
@NoArgsConstructor
public static class ProvisionedTp {
@JsonProperty("ReadCapacityUnits")
private long readCapacityUnits;
@JsonProperty("WriteCapacityUnits")
private long writeCapacityUnits;
}
}
I now this is already answered but you can use the provided class CreateTableRequest together with an object mapper such as Gson.
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class InitTables {
private AmazonDynamoDB dynamoDB;
private static String musicTable = "{\n" +
" \"TableName\" : \"Music\",\n" +
" \"KeySchema\": [\n" +
" {\n" +
" \"AttributeName\": \"Artist\",\n" +
" \"KeyType\": \"HASH\"\n" +
" },\n" +
" {\n" +
" \"AttributeName\": \"SongTitle\",\n" +
" \"KeyType\": \"RANGE\"\n" +
" }\n" +
" ],\n" +
" \"AttributeDefinitions\": [\n" +
" {\n" +
" \"AttributeName\": \"Artist\",\n" +
" \"AttributeType\": \"S\"\n" +
" },\n" +
" {\n" +
" \"AttributeName\": \"SongTitle\",\n" +
" \"AttributeType\": \"S\"\n" +
" }\n" +
" ],\n" +
" \"ProvisionedThroughput\": {\n" +
" \"ReadCapacityUnits\": 1,\n" +
" \"WriteCapacityUnits\": 1\n" +
" }\n" +
"}";
public InitTables(AmazonDynamoDB dynamoDB) {
this.dynamoDB = dynamoDB;
init();
}
public void init() {
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
.create();
CreateTableRequest createTableRequest = gson.fromJson(musicTable, CreateTableRequest.class);
dynamoDB.createTable(createTableRequest);
}
}