Skip to content

Commit

Permalink
Merge pull request vespa-engine#30411 from vespa-engine/freva/json
Browse files Browse the repository at this point in the history
Move Json to vespajlib
  • Loading branch information
hakonhall authored Feb 26, 2024
2 parents 904b7b0 + c36a7ba commit 7e89f23
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.restapi;

import ai.vespa.json.Json;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yahoo.container.jdisc.HttpResponse;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import ai.vespa.http.HttpURL;
import ai.vespa.http.HttpURL.Path;
import ai.vespa.http.HttpURL.Query;
import ai.vespa.json.Json;
import com.yahoo.slime.SlimeUtils;
import com.yahoo.time.TimeBudget;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
Expand Down Expand Up @@ -281,6 +283,11 @@ public <T> T read(Function<byte[], T> mapper) {
});
}

@Override
public Json readAsJson() {
return read(bytes -> Json.of(SlimeUtils.jsonToSlime(bytes)));
}

@Override
public void discard() throws UncheckedIOException, ResponseException {
handle((response, __) -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import ai.vespa.http.HttpURL;
import ai.vespa.http.HttpURL.Path;
import ai.vespa.http.HttpURL.Query;
import ai.vespa.json.Json;
import com.yahoo.time.TimeBudget;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.core5.http.ClassicHttpRequest;
Expand Down Expand Up @@ -140,6 +141,9 @@ default RequestBuilder parameters(String... pairs) {
/** Reads and maps the response, or throws if unsuccessful. */
<T> T read(Function<byte[], T> mapper);

/** Reads the response as a {@link Json}, or throws if unsuccessful. */
Json readAsJson();

/** Discards the response, but throws if unsuccessful. */
void discard();

Expand Down
11 changes: 11 additions & 0 deletions vespajlib/src/main/java/ai/vespa/json/InvalidJsonException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package ai.vespa.json;

/**
* @author freva
*/
public class InvalidJsonException extends IllegalArgumentException {
public InvalidJsonException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.yahoo.restapi;
package ai.vespa.json;

import com.yahoo.slime.Cursor;
import com.yahoo.slime.Inspector;
Expand Down Expand Up @@ -26,7 +26,7 @@
import static com.yahoo.slime.Type.STRING;

/**
* A {@link Slime} wrapper that throws {@link RestApiException.BadRequest} on missing members or invalid types.
* A {@link Slime} wrapper that throws {@link InvalidJsonException} on missing members or invalid types.
*
* @author bjorncs
*/
Expand Down Expand Up @@ -146,16 +146,16 @@ private void requireType(Type... types) {

private void requirePresent() { if (isMissing()) throw createMissingMemberException(); }

private RestApiException.BadRequest createInvalidTypeException(Type... expected) {
private InvalidJsonException createInvalidTypeException(Type... expected) {
var expectedTypesString = Arrays.stream(expected).map(this::toString).collect(Collectors.joining("' or '", "'", "'"));
var pathString = path.isEmpty() ? "JSON" : "JSON member '%s'".formatted(path);
return new RestApiException.BadRequest(
return new InvalidJsonException(
"Expected %s to be a %s but got '%s'"
.formatted(pathString, expectedTypesString, toString(inspector.type())));
}

private RestApiException.BadRequest createMissingMemberException() {
return new RestApiException.BadRequest(path.isEmpty() ? "Missing JSON" : "Missing JSON member '%s'".formatted(path));
private InvalidJsonException createMissingMemberException() {
return new InvalidJsonException(path.isEmpty() ? "Missing JSON" : "Missing JSON member '%s'".formatted(path));
}

private String toString(Type type) {
Expand Down
5 changes: 5 additions & 0 deletions vespajlib/src/main/java/ai/vespa/json/package-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
@ExportPackage
package ai.vespa.json;

import com.yahoo.osgi.annotation.ExportPackage;
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.yahoo.restapi;
package ai.vespa.json;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
* @author bjorncs
Expand Down Expand Up @@ -65,16 +67,16 @@ void throws_on_missing_and_invalid_members() {
""";
var json = Json.of(text);

var exception = assertThrows(RestApiException.BadRequest.class, () -> json.f("unknown").asString());
var exception = assertThrows(InvalidJsonException.class, () -> json.f("unknown").asString());
assertEquals("Missing JSON member 'unknown'", exception.getMessage());

exception = assertThrows(RestApiException.BadRequest.class, () -> json.a(0));
exception = assertThrows(InvalidJsonException.class, () -> json.a(0));
assertEquals("Expected JSON to be a 'array' but got 'object'", exception.getMessage());

exception = assertThrows(RestApiException.BadRequest.class, () -> json.f("string").f("unknown"));
exception = assertThrows(InvalidJsonException.class, () -> json.f("string").f("unknown"));
assertEquals("Expected JSON member 'string' to be a 'object' but got 'string'", exception.getMessage());

exception = assertThrows(RestApiException.BadRequest.class, () -> json.f("string").asLong());
exception = assertThrows(InvalidJsonException.class, () -> json.f("string").asLong());
assertEquals("Expected JSON member 'string' to be a 'integer' or 'float' but got 'string'", exception.getMessage());
}

Expand Down

0 comments on commit 7e89f23

Please sign in to comment.