Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add javadocs and fix visibility #37

Merged
merged 2 commits into from
Jul 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/main/java/io/github/orangain/jsonmatch/JsonMatch.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,28 @@

import java.util.Optional;


/**
* JSON matcher that compares actual JSON with a pattern JSON.
*/
public class JsonMatch {
/**
* Asserts that the actual JSON matches the pattern JSON.
* @param actualJson The actual JSON string.
* @param patternJson The pattern JSON string.
*/
public static void assertJsonMatches(String actualJson, String patternJson) {
jsonMatches(actualJson, patternJson)
.ifPresent(error -> {
throw new AssertionError(String.format("%s%nexpected:<%s> but was:<%s>", error.getMessage(), error.getExpected(), error.getActual()));
});
}

/**
* Checks if the actual JSON matches the pattern JSON.
* @param actualJson The actual JSON string.
* @param patternJson The pattern JSON string.
* @return An {@link Optional} of {@link JsonMatchError} if the actual JSON does not match the pattern JSON.
*/
public static Optional<JsonMatchError> jsonMatches(String actualJson, String patternJson) {
ObjectMapper mapper = JsonUtil.getObjectMapper();
JsonNode actualTree;
Expand Down
21 changes: 21 additions & 0 deletions src/main/java/io/github/orangain/jsonmatch/JsonMatchError.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,47 @@

import org.jetbrains.annotations.NotNull;

/**
* JSON match error.
*/
public class JsonMatchError {

private final String message;
private final String actual;
private final String expected;

/**
* Constructor of the JSON match error.
* @param message The error message.
* @param actual The actual JSON string.
* @param expected The expected JSON string.
*/
public JsonMatchError(@NotNull String message, @NotNull String actual, @NotNull String expected) {
this.message = message;
this.actual = actual;
this.expected = expected;
}

/**
* Get the error message.
* @return The error message.
*/
public String getMessage() {
return message;
}

/**
* Get the actual JSON string.
* @return The actual JSON string.
*/
public String getActual() {
return actual;
}

/**
* Get the expected JSON string.
* @return The expected JSON string.
*/
public String getExpected() {
return expected;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,22 @@

import org.jetbrains.annotations.NotNull;

/**
* JSON match error detail.
*/
public class JsonMatchErrorDetail {
private final JsonPath path;
private final String reason;
private final String actual;
private final String expected;

/**
* Constructor of the JSON match error detail.
* @param path The JSON path where the error occurred.
* @param actual The actual JSON string.
* @param expected The expected JSON string.
* @param reason The reason for the error.
*/
public JsonMatchErrorDetail(@NotNull JsonPath path, @NotNull String actual, @NotNull String expected, @NotNull String reason) {
this.path = path;
this.actual = actual;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,17 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Parser for JSON match patterns.
*/
public class JsonMatchPatternParser {
private static final Pattern ARRAY_PATTERN = Pattern.compile("\\A#\\[(\\d*)\\](.*)\\z");

/**
* Parse a JSON match pattern from a JSON node.
* @param jsonNode The JSON node to parse.
* @return The parsed JSON match pattern node.
*/
@NotNull
public static JsonPatternNode parse(@NotNull JsonNode jsonNode) {
if (jsonNode.isObject()) {
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/io/github/orangain/jsonmatch/JsonPath.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,40 @@

import org.jetbrains.annotations.NotNull;

/**
* Simple subset of JSON path. It supports only root, array item, and object field.
*/
public class JsonPath {
private final String path;

/**
* The root JSON path.
*/
public static JsonPath ROOT = new JsonPath("$");

/**
* Constructor of the JSON path.
* @param path The JSON path string.
*/
public JsonPath(@NotNull String path) {
this.path = path;
}

/**
* Get the JSON path for the array item.
* @param index The index of the array item.
* @return The JSON path for the array item.
*/
@NotNull
public JsonPath arrayItem(int index) {
return new JsonPath(path + "[" + index + "]");
}

/**
* Get the JSON path for the object field.
* @param fieldName The name of the object field.
* @return The JSON path for the object field.
*/
@NotNull
public JsonPath objectField(@NotNull String fieldName) {
return new JsonPath(path + "." + fieldName);
Expand Down
19 changes: 18 additions & 1 deletion src/main/java/io/github/orangain/jsonmatch/JsonStringAssert.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,34 @@

import org.assertj.core.api.AbstractAssert;


/**
* AssertJ assertion for JSON strings.
*/
public class JsonStringAssert extends AbstractAssert<JsonStringAssert, String> {

/**
* Constructor of the JSON string assertion.
* @param s The JSON string to make assertions on.
* @param selfType The class of the assertion.
*/
public JsonStringAssert(String s, Class<?> selfType) {
super(s, selfType);
}

/**
* Creates a new instance of JsonStringAssert allowing to perform assertions on the provided JSON string.
* @param actual The JSON string to make assertions on.
* @return A new instance of JsonStringAssert.
*/
public static JsonStringAssert assertThat(String actual) {
return new JsonStringAssert(actual, JsonStringAssert.class);
}

/**
* Asserts that the JSON string matches the pattern JSON string.
* @param patternJson The pattern JSON string.
* @return This assertion object.
*/
public JsonStringAssert jsonMatches(String patternJson) {
isNotNull();

Expand Down
12 changes: 12 additions & 0 deletions src/main/java/io/github/orangain/jsonmatch/JsonUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,28 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
* JSON utility class.
*/
public class JsonUtil {
private static ObjectMapper objectMapper;

/**
* Get the singleton instance of the Jackson {@link ObjectMapper}.
* @return The singleton instance of the Jackson {@link ObjectMapper}.
*/
static ObjectMapper getObjectMapper() {
if (objectMapper == null) {
objectMapper = new ObjectMapper();
}
return objectMapper;
}

/**
* Convert an object to a JSON string. This method is unchecked exception version of {@link ObjectMapper#writeValueAsString(Object)}.
* @param value The object to convert to a JSON string.
* @return The JSON string.
*/
public static String toJsonString(Object value) {
try {
return getObjectMapper().writeValueAsString(value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,17 @@
import java.util.List;
import java.util.Optional;

/**
* JSON array pattern node that matches a JSON array with a fixed number of elements and specific patterns for each element.
*/
public class ArrayLiteralPatternNode extends ArrayPatternNode {
private final List<JsonPatternNode> expectedChildren;

/**
* Constructor of the JSON array pattern node.
* @param expected The string representation of the expected JSON array pattern.
* @param expectedChildren The expected patterns for each element of the array.
*/
public ArrayLiteralPatternNode(@NotNull String expected, List<JsonPatternNode> expectedChildren) {
super(expected);
this.expectedChildren = expectedChildren;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,42 @@

import java.util.Optional;

/**
* JSON array pattern node that matches a JSON array. The pattern is represented by the "#array" marker.
*/
public class ArrayMarkerPatternNode extends ArrayPatternNode {
private final int expectedSize; // -1 when any size is allowed
private final JsonPatternNode expectedChildPattern; // null when any item is allowed
/**
* The expected size of the array. -1 means any size is allowed.
*/
private final int expectedSize;
/**
* The expected pattern for each element of the array. Null means any child pattern is allowed.
*/
private final JsonPatternNode expectedChildPattern;

/**
* Constructor of the JSON array pattern node with no expected size or child pattern.
* @param expected The string representation of the expected JSON array pattern.
*/
public ArrayMarkerPatternNode(@NotNull String expected) {
this(expected, null);
}

/**
* Constructor of the JSON array pattern node with child pattern but no expected size.
* @param expected The string representation of the expected JSON array pattern.
* @param expectedChildPattern The expected pattern for each element of the array.
*/
public ArrayMarkerPatternNode(@NotNull String expected, @Nullable JsonPatternNode expectedChildPattern) {
this(expected, -1, expectedChildPattern);
}

/**
* Constructor of the JSON array pattern node with expected size and child pattern.
* @param expected The string representation of the expected JSON array pattern.
* @param expectedSize The expected size of the array.
* @param expectedChildPattern The expected pattern for each element of the array.
*/
public ArrayMarkerPatternNode(@NotNull String expected, int expectedSize, @Nullable JsonPatternNode expectedChildPattern) {
super(expected);
this.expectedSize = expectedSize;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,18 @@

import java.util.Optional;

/**
* Base class for JSON array pattern nodes.
*/
public abstract class ArrayPatternNode extends JsonPatternNode {
public ArrayPatternNode(@NotNull String expected) {
/**
* Constructor of the JSON array pattern node.
* @param expected The string representation of the expected JSON array pattern.
*/
protected ArrayPatternNode(@NotNull String expected) {
super(expected);
}


@NotNull
@Override
public Optional<JsonMatchErrorDetail> matches(@NotNull JsonPath jsonPath, @NotNull JsonNode actualNode) {
Expand All @@ -28,9 +34,21 @@ public Optional<JsonMatchErrorDetail> matches(@NotNull JsonPath jsonPath, @NotNu
return childrenMatches(jsonPath, actualNode);
}

/**
* Checks if the size of the actual JSON array node matches the pattern node.
* @param jsonPath The JSON path to the actual JSON node.
* @param actualNode The actual JSON node.
* @return An empty optional if the size matches, or an error detail if it does not match.
*/
@NotNull
protected abstract Optional<JsonMatchErrorDetail> sizeMatches(@NotNull JsonPath jsonPath, @NotNull JsonNode actualNode);

/**
* Checks if the children of the actual JSON array node matches the pattern node.
* @param jsonPath The JSON path to the actual JSON node.
* @param actualNode The actual JSON node.
* @return An empty optional if the children matches, or an error detail if they do not match.
*/
@NotNull
protected abstract Optional<JsonMatchErrorDetail> childrenMatches(@NotNull JsonPath jsonPath, @NotNull JsonNode actualNode);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,48 @@

import java.util.Optional;

/**
* Base class for JSON pattern nodes.
*/
public abstract class JsonPatternNode {
/**
* The string representation of the expected JSON pattern.
*/
private final String expected;

public JsonPatternNode(@NotNull String expected) {
/**
* Constructor of the JSON pattern node.
* @param expected The string representation of the expected JSON pattern.
*/
protected JsonPatternNode(@NotNull String expected) {
this.expected = expected;
}

/**
* Matches the JSON pattern node against the actual JSON node.
* @param path The JSON path to the actual JSON node.
* @param actualNode The actual JSON node.
* @return An empty optional if the actual JSON node matches the pattern node, or an error detail if it does not match.
*/
@NotNull
public abstract Optional<JsonMatchErrorDetail> matches(@NotNull JsonPath path, @NotNull JsonNode actualNode);

/**
* Creates an error detail.
* @param path The JSON path to the actual JSON node.
* @param actualNode The actual JSON node.
* @param reason The reason why the actual JSON node does not match the pattern node.
* @return An error detail.
*/
@NotNull
protected JsonMatchErrorDetail error(@NotNull JsonPath path, @NotNull JsonNode actualNode, @NotNull String reason) {
return new JsonMatchErrorDetail(path, actualNode.toString(), expected, reason);
}

/**
* Returns if the pattern node can be missing.
* @return True if the pattern node can be missing, false otherwise.
*/
protected boolean canBeMissing() {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,17 @@
import java.util.Set;
import java.util.stream.Collectors;

/**
* JSON object pattern node that matches a JSON object with fixed key-value pairs.
*/
public class ObjectLiteralPatternNode extends ObjectPatternNode {
private final Map<String, JsonPatternNode> expectedChildren;

/**
* Constructor of the JSON object pattern node.
* @param expected The string representation of the expected JSON object pattern.
* @param expectedChildren The expected pairs of key and value pattern node.
*/
public ObjectLiteralPatternNode(@NotNull String expected, @NotNull Map<String, JsonPatternNode> expectedChildren) {
super(expected);
this.expectedChildren = expectedChildren;
Expand Down
Loading