diff --git a/google-cloud-spanner/clirr-ignored-differences.xml b/google-cloud-spanner/clirr-ignored-differences.xml
index 75df772d76..0efd90a38d 100644
--- a/google-cloud-spanner/clirr-ignored-differences.xml
+++ b/google-cloud-spanner/clirr-ignored-differences.xml
@@ -659,4 +659,46 @@
void setOptimizerStatisticsPackage(java.lang.String)
+
+
+ 7013
+ com/google/cloud/spanner/AbstractStructReader
+ java.lang.String getJsonInternal(int)
+
+
+ 7013
+ com/google/cloud/spanner/AbstractStructReader
+ java.util.List getJsonListInternal(int)
+
+
+ 7012
+ com/google/cloud/spanner/StructReader
+ java.lang.String getJson(int)
+
+
+ 7012
+ com/google/cloud/spanner/StructReader
+ java.lang.String getJson(java.lang.String)
+
+
+ 7012
+ com/google/cloud/spanner/StructReader
+ java.util.List getJsonList(int)
+
+
+ 7012
+ com/google/cloud/spanner/StructReader
+ java.util.List getJsonList(java.lang.String)
+
+
+ 7013
+ com/google/cloud/spanner/Value
+ java.lang.String getJson()
+
+
+ 7013
+ com/google/cloud/spanner/Value
+ java.util.List getJsonArray()
+
+
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractResultSet.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractResultSet.java
index 09b824038e..54bfc3f545 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractResultSet.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractResultSet.java
@@ -378,6 +378,9 @@ private Object writeReplace() {
case STRING:
builder.set(fieldName).to((String) value);
break;
+ case JSON:
+ builder.set(fieldName).to(Value.json((String) value));
+ break;
case BYTES:
builder.set(fieldName).to((ByteArray) value);
break;
@@ -404,6 +407,9 @@ private Object writeReplace() {
case STRING:
builder.set(fieldName).toStringArray((Iterable) value);
break;
+ case JSON:
+ builder.set(fieldName).toJsonArray((Iterable) value);
+ break;
case BYTES:
builder.set(fieldName).toBytesArray((Iterable) value);
break;
@@ -480,6 +486,7 @@ private static Object decodeValue(Type fieldType, com.google.protobuf.Value prot
case NUMERIC:
return new BigDecimal(proto.getStringValue());
case STRING:
+ case JSON:
checkType(fieldType, proto, KindCase.STRING_VALUE);
return proto.getStringValue();
case BYTES:
@@ -543,6 +550,7 @@ static Object decodeArrayValue(Type elementType, ListValue listValue) {
return list;
}
case STRING:
+ case JSON:
return Lists.transform(
listValue.getValuesList(),
input -> input.getKindCase() == KindCase.NULL_VALUE ? null : input.getStringValue());
@@ -654,6 +662,11 @@ protected String getStringInternal(int columnIndex) {
return (String) rowData.get(columnIndex);
}
+ @Override
+ protected String getJsonInternal(int columnIndex) {
+ return (String) rowData.get(columnIndex);
+ }
+
@Override
protected ByteArray getBytesInternal(int columnIndex) {
return (ByteArray) rowData.get(columnIndex);
@@ -782,6 +795,12 @@ protected List getStringListInternal(int columnIndex) {
return Collections.unmodifiableList((List) rowData.get(columnIndex));
}
+ @Override
+ @SuppressWarnings("unchecked") // We know ARRAY produces a List.
+ protected List getJsonListInternal(int columnIndex) {
+ return Collections.unmodifiableList((List) rowData.get(columnIndex));
+ }
+
@Override
@SuppressWarnings("unchecked") // We know ARRAY produces a List.
protected List getBytesListInternal(int columnIndex) {
@@ -1308,6 +1327,11 @@ protected String getStringInternal(int columnIndex) {
return currRow().getStringInternal(columnIndex);
}
+ @Override
+ protected String getJsonInternal(int columnIndex) {
+ return currRow().getJsonInternal(columnIndex);
+ }
+
@Override
protected ByteArray getBytesInternal(int columnIndex) {
return currRow().getBytesInternal(columnIndex);
@@ -1368,6 +1392,11 @@ protected List getStringListInternal(int columnIndex) {
return currRow().getStringListInternal(columnIndex);
}
+ @Override
+ protected List getJsonListInternal(int columnIndex) {
+ return currRow().getJsonListInternal(columnIndex);
+ }
+
@Override
protected List getBytesListInternal(int columnIndex) {
return currRow().getBytesListInternal(columnIndex);
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractStructReader.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractStructReader.java
index 9b3f1810eb..185ab03eef 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractStructReader.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractStructReader.java
@@ -43,6 +43,10 @@ public abstract class AbstractStructReader implements StructReader {
protected abstract String getStringInternal(int columnIndex);
+ protected String getJsonInternal(int columnIndex) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
protected abstract ByteArray getBytesInternal(int columnIndex);
protected abstract Timestamp getTimestampInternal(int columnIndex);
@@ -69,6 +73,10 @@ protected Value getValueInternal(int columnIndex) {
protected abstract List getStringListInternal(int columnIndex);
+ protected List getJsonListInternal(int columnIndex) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
protected abstract List getBytesListInternal(int columnIndex);
protected abstract List getTimestampListInternal(int columnIndex);
@@ -162,6 +170,19 @@ public String getString(String columnName) {
return getStringInternal(columnIndex);
}
+ @Override
+ public String getJson(int columnIndex) {
+ checkNonNullOfType(columnIndex, Type.json(), columnIndex);
+ return getJsonInternal(columnIndex);
+ }
+
+ @Override
+ public String getJson(String columnName) {
+ int columnIndex = getColumnIndex(columnName);
+ checkNonNullOfType(columnIndex, Type.json(), columnName);
+ return getJsonInternal(columnIndex);
+ }
+
@Override
public ByteArray getBytes(int columnIndex) {
checkNonNullOfType(columnIndex, Type.bytes(), columnIndex);
@@ -317,6 +338,19 @@ public List getStringList(String columnName) {
return getStringListInternal(columnIndex);
}
+ @Override
+ public List getJsonList(int columnIndex) {
+ checkNonNullOfType(columnIndex, Type.array(Type.json()), columnIndex);
+ return getJsonListInternal(columnIndex);
+ }
+
+ @Override
+ public List getJsonList(String columnName) {
+ int columnIndex = getColumnIndex(columnName);
+ checkNonNullOfType(columnIndex, Type.array(Type.json()), columnName);
+ return getJsonListInternal(columnIndex);
+ }
+
@Override
public List getBytesList(int columnIndex) {
checkNonNullOfType(columnIndex, Type.array(Type.bytes()), columnIndex);
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/ForwardingStructReader.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/ForwardingStructReader.java
index d5f9488178..e225bdcc1b 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/ForwardingStructReader.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/ForwardingStructReader.java
@@ -156,6 +156,18 @@ public String getString(String columnName) {
return delegate.get().getString(columnName);
}
+ @Override
+ public String getJson(int columnIndex) {
+ checkValidState();
+ return delegate.get().getJson(columnIndex);
+ }
+
+ @Override
+ public String getJson(String columnName) {
+ checkValidState();
+ return delegate.get().getJson(columnName);
+ }
+
@Override
public ByteArray getBytes(int columnIndex) {
checkValidState();
@@ -286,6 +298,18 @@ public List getStringList(String columnName) {
return delegate.get().getStringList(columnName);
}
+ @Override
+ public List getJsonList(int columnIndex) {
+ checkValidState();
+ return delegate.get().getJsonList(columnIndex);
+ }
+
+ @Override
+ public List getJsonList(String columnName) {
+ checkValidState();
+ return delegate.get().getJsonList(columnName);
+ }
+
@Override
public List getBytesList(int columnIndex) {
checkValidState();
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Key.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Key.java
index cf9a839585..15d4e995bf 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Key.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Key.java
@@ -65,6 +65,7 @@ private Key(List