diff --git a/data/pom.xml b/data/pom.xml
index 379fc019..2a135821 100644
--- a/data/pom.xml
+++ b/data/pom.xml
@@ -170,11 +170,6 @@
httpcore
${httpcore.version}
-
- org.json
- json
- ${json.version}
-
org.jetbrains
annotations
@@ -282,5 +277,21 @@
com.fasterxml.jackson.core
${fasterxml.jackson.core.version}
+
+
+ jackson-core
+ com.fasterxml.jackson.core
+ ${fasterxml.jackson.core.version}
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+ ${fasterxml.jackson.core.version}
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jdk8
+ ${fasterxml.jackson.core.version}
+
diff --git a/data/src/main/java/com/microsoft/azure/kusto/data/ClientImpl.java b/data/src/main/java/com/microsoft/azure/kusto/data/ClientImpl.java
index 3a3e59af..b0b391e6 100644
--- a/data/src/main/java/com/microsoft/azure/kusto/data/ClientImpl.java
+++ b/data/src/main/java/com/microsoft/azure/kusto/data/ClientImpl.java
@@ -3,6 +3,8 @@
package com.microsoft.azure.kusto.data;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import com.microsoft.azure.kusto.data.auth.CloudInfo;
import com.microsoft.azure.kusto.data.auth.ConnectionStringBuilder;
import com.microsoft.azure.kusto.data.auth.TokenProviderBase;
@@ -16,8 +18,6 @@
import org.apache.http.HttpHeaders;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
-import org.json.JSONException;
-import org.json.JSONObject;
import java.io.InputStream;
import java.net.URI;
@@ -45,6 +45,8 @@ public class ClientImpl implements Client, StreamingClient {
private final CloseableHttpClient httpClient;
private boolean endpointValidated = false;
+ private ObjectMapper objectMapper = Utils.getObjectMapper();
+
public ClientImpl(ConnectionStringBuilder csb) throws URISyntaxException {
this(csb, HttpClientProperties.builder().build());
}
@@ -308,25 +310,17 @@ private Map generateIngestAndCommandHeaders(ClientRequestPropert
return headers;
}
- private String generateCommandPayload(String database, String command, ClientRequestProperties properties, String clusterEndpoint)
- throws DataClientException {
- String jsonPayload;
- try {
- JSONObject json = new JSONObject()
- .put("db", database)
- .put("csl", command);
+ private String generateCommandPayload(String database, String command, ClientRequestProperties properties, String clusterEndpoint) {
- if (properties != null) {
- json.put("properties", properties.toString());
- }
+ ObjectNode json = objectMapper.createObjectNode()
+ .put("db", database)
+ .put("csl", command);
- jsonPayload = json.toString();
- } catch (JSONException e) {
- throw new DataClientException(clusterEndpoint,
- String.format(clusterEndpoint, "Error executing command '%s' in database '%s'. Setting up request payload failed.", command, database), e);
+ if (properties != null) {
+ json.put("properties", properties.toString());
}
- return jsonPayload;
+ return json.toString();
}
private void addCommandHeaders(Map headers) {
diff --git a/data/src/main/java/com/microsoft/azure/kusto/data/ClientRequestProperties.java b/data/src/main/java/com/microsoft/azure/kusto/data/ClientRequestProperties.java
index 4ad79547..29430a12 100644
--- a/data/src/main/java/com/microsoft/azure/kusto/data/ClientRequestProperties.java
+++ b/data/src/main/java/com/microsoft/azure/kusto/data/ClientRequestProperties.java
@@ -3,6 +3,9 @@
package com.microsoft.azure.kusto.data;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import com.microsoft.azure.kusto.data.format.CslBoolFormat;
import com.microsoft.azure.kusto.data.format.CslDateTimeFormat;
import com.microsoft.azure.kusto.data.format.CslIntFormat;
@@ -12,8 +15,6 @@
import com.microsoft.azure.kusto.data.format.CslUuidFormat;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.ParseException;
-import org.json.JSONException;
-import org.json.JSONObject;
import java.io.Serializable;
import java.time.Duration;
@@ -190,57 +191,53 @@ public void setTimeoutInMilliSec(Long timeoutInMs) {
options.put(OPTION_SERVER_TIMEOUT, timeoutInMs);
}
- JSONObject toJson() {
- try {
- JSONObject optionsAsJSON = new JSONObject(this.options);
- Object timeoutObj = getOption(OPTION_SERVER_TIMEOUT);
-
- if (timeoutObj != null) {
- String timeoutString = "";
- if (timeoutObj instanceof Long) {
- Duration duration = Duration.ofMillis((Long) timeoutObj);
- timeoutString = Utils.formatDurationAsTimespan(duration);
- } else if (timeoutObj instanceof String) {
- timeoutString = (String) timeoutObj;
- } else if (timeoutObj instanceof Integer) {
- Duration duration = Duration.ofMillis((Integer) timeoutObj);
- timeoutString = Utils.formatDurationAsTimespan(duration);
- }
- optionsAsJSON.put(OPTION_SERVER_TIMEOUT, timeoutString);
+ JsonNode toJson() {
+ ObjectNode optionsAsJSON = Utils.getObjectMapper().valueToTree(this.options);
+ Object timeoutObj = getOption(OPTION_SERVER_TIMEOUT);
+
+ if (timeoutObj != null) {
+ String timeoutString = "";
+ if (timeoutObj instanceof Long) {
+ Duration duration = Duration.ofMillis((Long) timeoutObj);
+ timeoutString = Utils.formatDurationAsTimespan(duration);
+ } else if (timeoutObj instanceof String) {
+ timeoutString = (String) timeoutObj;
+ } else if (timeoutObj instanceof Integer) {
+ Duration duration = Duration.ofMillis((Integer) timeoutObj);
+ timeoutString = Utils.formatDurationAsTimespan(duration);
}
- JSONObject json = new JSONObject();
- json.put(OPTIONS_KEY, optionsAsJSON);
- json.put(PARAMETERS_KEY, new JSONObject(this.parameters));
- return json;
- } catch (JSONException e) {
- return null;
+ optionsAsJSON.put(OPTION_SERVER_TIMEOUT, timeoutString);
}
+ ObjectNode json = Utils.getObjectMapper().createObjectNode();
+ json.set(OPTIONS_KEY, optionsAsJSON);
+ json.set(PARAMETERS_KEY, Utils.getObjectMapper().valueToTree(this.parameters));
+ return json;
}
public String toString() {
return toJson().toString();
}
- public static ClientRequestProperties fromString(String json) throws JSONException {
+ public static ClientRequestProperties fromString(String json) throws JsonProcessingException {
if (StringUtils.isNotBlank(json)) {
ClientRequestProperties crp = new ClientRequestProperties();
- JSONObject jsonObj = new JSONObject(json);
- Iterator it = jsonObj.keys();
+ JsonNode jsonObj = Utils.getObjectMapper().readTree(json);
+ Iterator it = jsonObj.fieldNames();
while (it.hasNext()) {
String propertyName = it.next();
if (propertyName.equals(OPTIONS_KEY)) {
- JSONObject optionsJson = (JSONObject) jsonObj.get(propertyName);
- Iterator optionsIt = optionsJson.keys();
+ JsonNode optionsJson = jsonObj.get(propertyName);
+ Iterator optionsIt = optionsJson.fieldNames();
while (optionsIt.hasNext()) {
String optionName = optionsIt.next();
- crp.setOption(optionName, optionsJson.get(optionName));
+ crp.setOption(optionName, optionsJson.get(optionName).asText());
}
} else if (propertyName.equals(PARAMETERS_KEY)) {
- JSONObject parameters = (JSONObject) jsonObj.get(propertyName);
- Iterator parametersIt = parameters.keys();
+ JsonNode parameters = jsonObj.get(propertyName);
+ Iterator parametersIt = parameters.fieldNames();
while (parametersIt.hasNext()) {
String parameterName = parametersIt.next();
- crp.setParameter(parameterName, parameters.get(parameterName));
+ crp.setParameter(parameterName, parameters.get(parameterName).asText());
}
}
}
diff --git a/data/src/main/java/com/microsoft/azure/kusto/data/KustoOperationResult.java b/data/src/main/java/com/microsoft/azure/kusto/data/KustoOperationResult.java
index 91b49d09..4e14d0c6 100644
--- a/data/src/main/java/com/microsoft/azure/kusto/data/KustoOperationResult.java
+++ b/data/src/main/java/com/microsoft/azure/kusto/data/KustoOperationResult.java
@@ -3,13 +3,21 @@
package com.microsoft.azure.kusto.data;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.microsoft.azure.kusto.data.exceptions.JsonPropertyMissingException;
import com.microsoft.azure.kusto.data.exceptions.KustoServiceQueryError;
-import org.json.JSONArray;
-import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.lang.invoke.MethodHandles;
import java.util.*;
public class KustoOperationResult implements Iterator {
+
+ private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static final Map tablesKindsMap = new HashMap() {
{
put("QueryResult", WellKnownDataSet.PrimaryResult);
@@ -26,6 +34,8 @@ public class KustoOperationResult implements Iterator {
private final List resultTables = new ArrayList<>();
private final Iterator it;
+ private final ObjectMapper objectMapper = Utils.getObjectMapper();
+
public KustoOperationResult(String response, String version) throws KustoServiceQueryError {
if (version.contains("v2")) {
createFromV2Response(response);
@@ -58,11 +68,20 @@ public KustoResultSetTable getPrimaryResults() {
}
private void createFromV1Response(String response) throws KustoServiceQueryError {
- JSONObject jsonObject = new JSONObject(response);
- JSONArray jsonArray = jsonObject.getJSONArray(TABLES_LIST_PROPERTY_NAME);
- for (int i = 0; i < jsonArray.length(); i++) {
- JSONObject table = jsonArray.getJSONObject(i);
- resultTables.add(new KustoResultSetTable(table));
+ try {
+ JsonNode jsonObject = objectMapper.readTree(response);
+ if (jsonObject.has(TABLES_LIST_PROPERTY_NAME) && jsonObject.get(TABLES_LIST_PROPERTY_NAME).isArray()) {
+ ArrayNode jsonArray = (ArrayNode) jsonObject.get(TABLES_LIST_PROPERTY_NAME);
+ for (int i = 0; i < jsonArray.size(); i++) {
+ JsonNode table = jsonArray.get(i);
+ resultTables.add(new KustoResultSetTable(table));
+ }
+ } else {
+ throw new JsonPropertyMissingException("Tables Property missing from V1 response json");
+ }
+ } catch (JsonProcessingException | JsonPropertyMissingException e) {
+ log.error("Json processing error occured while parsing string to json with exception", e);
+ throw new KustoServiceQueryError("Json processing error occurred while parsing string to json with exception " + e.getMessage());
}
if (resultTables.size() <= 2) {
@@ -87,12 +106,26 @@ private void createFromV1Response(String response) throws KustoServiceQueryError
}
private void createFromV2Response(String response) throws KustoServiceQueryError {
- JSONArray jsonArray = new JSONArray(response);
- for (int i = 0; i < jsonArray.length(); i++) {
- JSONObject table = jsonArray.getJSONObject(i);
- if (table.optString(FRAME_TYPE_PROPERTY_NAME).equals(DATA_TABLE_FRAME_TYPE_PROPERTY_NAME)) {
- resultTables.add(new KustoResultSetTable(table));
+ ArrayNode jsonArray;
+ try {
+ JsonNode jsonNode = objectMapper.readTree(response);
+ if (jsonNode.isArray()) {
+ jsonArray = (ArrayNode) jsonNode;
+ for (JsonNode node : jsonArray) {
+ if (node.has(FRAME_TYPE_PROPERTY_NAME) && node.get(FRAME_TYPE_PROPERTY_NAME).asText().equals(DATA_TABLE_FRAME_TYPE_PROPERTY_NAME)) {
+ resultTables.add(new KustoResultSetTable(node));
+ }
+ }
+ } else {
+ throw new JsonPropertyMissingException("There is no array in the response which can be parsed");
}
+ } catch (JsonProcessingException | JsonPropertyMissingException jsonException) {
+ log.error("Json processing error occured while parsing string to json with exception", jsonException);
+ throw new KustoServiceQueryError(
+ "Json processing error occurred while parsing string to json with exception " + jsonException.getMessage());
+ } catch (NullPointerException nullPointerException) {
+ log.error("Null pointer exception thrown due to invalid v2 response", nullPointerException);
+ throw new KustoServiceQueryError("Null pointer exception thrown due to invalid v2 response " + nullPointerException.getMessage());
}
}
}
diff --git a/data/src/main/java/com/microsoft/azure/kusto/data/KustoResultSetTable.java b/data/src/main/java/com/microsoft/azure/kusto/data/KustoResultSetTable.java
index 00712eef..63cc8ce3 100644
--- a/data/src/main/java/com/microsoft/azure/kusto/data/KustoResultSetTable.java
+++ b/data/src/main/java/com/microsoft/azure/kusto/data/KustoResultSetTable.java
@@ -3,12 +3,15 @@
package com.microsoft.azure.kusto.data;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeType;
+import com.microsoft.azure.kusto.data.exceptions.JsonPropertyMissingException;
import com.microsoft.azure.kusto.data.exceptions.KustoServiceQueryError;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat;
-import org.json.JSONArray;
-import org.json.JSONObject;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
@@ -37,7 +40,9 @@ public class KustoResultSetTable {
private static final String ROWS_PROPERTY_NAME = "Rows";
private static final String EXCEPTIONS_PROPERTY_NAME = "Exceptions";
private static final String EXCEPTIONS_MESSAGE = "Query execution failed with multiple inner exceptions";
- private static DateTimeFormatter kustoDateTimeFormatter = new DateTimeFormatterBuilder().parseCaseInsensitive()
+
+ private static final String EMPTY_STRING = "";
+ private static final DateTimeFormatter kustoDateTimeFormatter = new DateTimeFormatterBuilder().parseCaseInsensitive()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME).appendLiteral('Z').toFormatter();
private final List> rows;
@@ -77,54 +82,96 @@ void setTableKind(WellKnownDataSet tableKind) {
this.tableKind = tableKind;
}
- protected KustoResultSetTable(JSONObject jsonTable) throws KustoServiceQueryError {
- tableName = jsonTable.optString(TABLE_NAME_PROPERTY_NAME);
- tableId = jsonTable.optString(TABLE_ID_PROPERTY_NAME);
- String tableKindString = jsonTable.optString(TABLE_KIND_PROPERTY_NAME);
+ protected KustoResultSetTable(JsonNode jsonTable) throws KustoServiceQueryError, JsonProcessingException, JsonPropertyMissingException {
+ if (jsonTable.has(TABLE_NAME_PROPERTY_NAME)) {
+ tableName = jsonTable.get(TABLE_NAME_PROPERTY_NAME).asText();
+ }
+ if (jsonTable.has(TABLE_ID_PROPERTY_NAME)) {
+ tableId = jsonTable.get(TABLE_ID_PROPERTY_NAME).asText();
+ }
+ tableId = jsonTable.has(TABLE_ID_PROPERTY_NAME) ? jsonTable.get(TABLE_ID_PROPERTY_NAME).asText() : EMPTY_STRING;
+ String tableKindString = jsonTable.has(TABLE_KIND_PROPERTY_NAME) ? jsonTable.get(TABLE_KIND_PROPERTY_NAME).asText() : EMPTY_STRING;
tableKind = StringUtils.isBlank(tableKindString) ? null : WellKnownDataSet.valueOf(tableKindString);
- JSONArray columnsJson = jsonTable.optJSONArray(COLUMNS_PROPERTY_NAME);
- if (columnsJson != null) {
- columnsAsArray = new KustoResultColumn[columnsJson.length()];
- for (int i = 0; i < columnsJson.length(); i++) {
- JSONObject jsonCol = columnsJson.getJSONObject(i);
- String columnType = jsonCol.optString(COLUMN_TYPE_PROPERTY_NAME);
- if (columnType.equals("")) {
- columnType = jsonCol.optString(COLUMN_TYPE_SECOND_PROPERTY_NAME);
+
+ if (jsonTable.has(COLUMNS_PROPERTY_NAME) && jsonTable.get(COLUMNS_PROPERTY_NAME).getNodeType() == JsonNodeType.ARRAY) {
+ ArrayNode columnsJson = (ArrayNode) jsonTable.get(COLUMNS_PROPERTY_NAME);
+ if (columnsJson != null) {
+ columnsAsArray = new KustoResultColumn[columnsJson.size()];
+ for (int i = 0; i < columnsJson.size(); i++) {
+ JsonNode jsonCol = columnsJson.get(i);
+
+ String columnType = jsonCol.has(COLUMN_TYPE_PROPERTY_NAME) ? jsonCol.get(COLUMN_TYPE_PROPERTY_NAME).asText() : EMPTY_STRING;
+ if (columnType.equals("")) {
+ columnType = jsonCol.has(COLUMN_TYPE_SECOND_PROPERTY_NAME) ? jsonCol.get(COLUMN_TYPE_SECOND_PROPERTY_NAME).asText() : EMPTY_STRING;
+ }
+ if (jsonCol.has(COLUMN_NAME_PROPERTY_NAME)) {
+ KustoResultColumn col = new KustoResultColumn(
+ jsonCol.has(COLUMN_NAME_PROPERTY_NAME) ? jsonCol.get(COLUMN_NAME_PROPERTY_NAME).asText() : EMPTY_STRING, columnType, i);
+ columnsAsArray[i] = col;
+ columns.put(jsonCol.has(COLUMN_NAME_PROPERTY_NAME) ? jsonCol.get(COLUMN_NAME_PROPERTY_NAME).asText() : EMPTY_STRING, col);
+ } else {
+ throw new JsonPropertyMissingException("Column Name property is missing in the json response");
+ }
}
- KustoResultColumn col = new KustoResultColumn(jsonCol.getString(COLUMN_NAME_PROPERTY_NAME), columnType, i);
- columnsAsArray[i] = col;
- columns.put(jsonCol.getString(COLUMN_NAME_PROPERTY_NAME), col);
}
}
- JSONArray exceptions;
- JSONArray jsonRows = jsonTable.optJSONArray(ROWS_PROPERTY_NAME);
+ ArrayNode exceptions;
+ ArrayNode jsonRows = null;
+ if (jsonTable.has(ROWS_PROPERTY_NAME) && jsonTable.get(ROWS_PROPERTY_NAME).getNodeType() == JsonNodeType.ARRAY) {
+ jsonRows = (ArrayNode) jsonTable.get(ROWS_PROPERTY_NAME);
+ }
if (jsonRows != null) {
List> values = new ArrayList<>();
- for (int i = 0; i < jsonRows.length(); i++) {
- Object row = jsonRows.get(i);
- if (row instanceof JSONObject) {
- exceptions = ((JSONObject) row).optJSONArray(EXCEPTIONS_PROPERTY_NAME);
+ for (int i = 0; i < jsonRows.size(); i++) {
+ JsonNode row = jsonRows.get(i);
+ if (jsonRows.get(i).getNodeType() == JsonNodeType.OBJECT) {
+ exceptions = row.has(EXCEPTIONS_PROPERTY_NAME) ? ((ArrayNode) row.get(EXCEPTIONS_PROPERTY_NAME)) : null;
if (exceptions != null) {
- if (exceptions.length() == 1) {
- String message = exceptions.getString(0);
+ if (exceptions.size() == 1) {
+ String message = exceptions.get(0).asText();
throw new KustoServiceQueryError(message);
} else {
throw new KustoServiceQueryError(exceptions, false, EXCEPTIONS_MESSAGE);
}
} else {
- throw new KustoServiceQueryError(((JSONObject) row).getJSONArray(
- "OneApiErrors"), true, EXCEPTIONS_MESSAGE);
+ throw new KustoServiceQueryError((ArrayNode) row.get("OneApiErrors"), true, EXCEPTIONS_MESSAGE);
}
}
- JSONArray rowAsJsonArray = jsonRows.getJSONArray(i);
+ ArrayNode rowAsJsonArray = (ArrayNode) jsonRows.get(i);
List