Il existe une bibliothèque appelée JSONassert qui compare JSON en Java, mais cette fois, lors de la comparaison de JSON avec cette bibliothèque, des expressions normales sont utilisées pour la correspondance de valeurs. Je voudrais brièvement présenter comment l'appliquer.
Utilisez CustomComparator
pour spécifier l'élément pour lequel vous souhaitez traiter la valeur attendue comme une expression régulière, comme indiqué ci-dessous.
JSON à vérifier
{
"array": [
1,
2
],
"id": 100,
"type": "foo",
"object": {
"name": "Kazuki",
"token": "ac648657-797e-49f7-9563-150c9b5c2284"
}
}
JSON qui exprime la valeur attendue
{
"array": [
1,
2
],
"id": 100,
"type": "foo",
"object": {
"name": "Kazuki",
"token": "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
}
}
Voici un exemple de spécification lors de la comparaison de ʻobject.token` à l'aide d'une expression régulière.
Exemple d'appel de méthode de comparaison
JSONAssert.assertEquals(expectedJson.toString(2), actualJson.toString(2),
new CustomComparator(JSONCompareMode.STRICT,
new Customization("object.token", new RegularExpressionValueMatcher<>()) //Correspondance en utilisant le modèle spécifié pour la valeur attendue
)
);
Vous pouvez également spécifier un modèle lors de la vérification, comme indiqué ci-dessous.
Exemple de spécification d'un modèle lors de la vérification
JSONAssert.assertEquals(expectedJson.toString(2), actualJson.toString(2),
new CustomComparator(JSONCompareMode.STRICT,
new Customization("object.token", new RegularExpressionValueMatcher<>("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")) //Correspondance à l'aide du modèle spécifié ici sans utiliser la valeur décrite dans la valeur attendue JSON
)
);
Dans la fonctionnalité standard, l'application d'expressions régulières est élément par élément (pour autant que je sache) (peut-être qu'il existe un support pour la spécification de chemins de type générique!?). Donc ... je voudrais créer mon propre JSONComparator
qui peut correspondre à tous les éléments en utilisant des expressions régulières sans utiliser CustomComparator
.
Exemple de création de JSONComparator
public class RegularExpressionComparator extends DefaultComparator {
private static final RegularExpressionValueMatcher<Object> REGEX_VALUE_MATCHER = new RegularExpressionValueMatcher<>();
private final ValueMatcher<Object> matcher;
public RegularExpressionComparator(JSONCompareMode mode) {
super(mode);
//Adopter une méthode de comparaison une fois avec une correspondance exacte, et dans le cas de NG, revenir à une correspondance avec une expression régulière
//Étant donné que la plupart des éléments peuvent être mis en correspondance exactement, le coût de traitement peut être réduit par rapport à la correspondance inconditionnelle par expression régulière (devrait).
this.matcher = (actual, expected) -> Objects.equals(actual, expected) ||
expected instanceof String && REGEX_VALUE_MATCHER.equal(actual, expected);
}
@Override
public void compareValues(String prefix, Object expectedValue, Object actualValue, JSONCompareResult result) throws JSONException {
if (actualValue instanceof JSONArray || actualValue instanceof JSONObject) {
//récipient(Objet + tableau)S'il s'agit d'un objet, transférez-le dans l'implémentation par défaut
super.compareValues(prefix, expectedValue, actualValue, result);
} else {
//Pour les valeurs (chaînes, nombres, booléens), appelez ValueMatcher avec prise en charge des expressions régulières pour comparer
try {
if (!matcher.equal(actualValue, expectedValue)) {
//Gestion des erreurs lorsqu'il est jugé qu'il y a une discordance quand il n'est pas mis en correspondance par l'expression régulière
result.fail(prefix, expectedValue, actualValue);
}
} catch (ValueMatcherException e) {
//Gestion des erreurs lorsqu'une discordance est déterminée par correspondance avec une expression régulière
result.fail(prefix, e);
}
}
}
}
Pour référence, je vais également coller le cas de test créé au moment de la vérification.
package com.example.assertdemo;
import java.util.Objects;
import java.util.UUID;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Test;
import org.skyscreamer.jsonassert.JSONAssert;
import org.skyscreamer.jsonassert.JSONCompareMode;
import org.skyscreamer.jsonassert.JSONCompareResult;
import org.skyscreamer.jsonassert.RegularExpressionValueMatcher;
import org.skyscreamer.jsonassert.ValueMatcher;
import org.skyscreamer.jsonassert.ValueMatcherException;
import org.skyscreamer.jsonassert.comparator.DefaultComparator;
public class JSONAssertRegexTests {
@Test
public void regexAssert() throws JSONException {
JSONObject expectedJson = new JSONObject();
{
JSONArray array = new JSONArray();
array.put(1);
array.put(2);
JSONObject object = new JSONObject();
object.put("name", "Kazuki");
object.put("token", "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}");
expectedJson.put("id", 100);
expectedJson.put("type", "foo");
expectedJson.put("array", array);
expectedJson.put("object", object);
System.out.println("-----expectedJson------");
System.out.println(expectedJson.toString(2));
}
JSONObject actualJson = new JSONObject();
{
JSONArray array = new JSONArray();
array.put(1);
array.put(2);
actualJson.put("id", 100);
actualJson.put("array", array);
JSONObject object = new JSONObject();
object.put("name", "Kazuki");
object.put("token", UUID.randomUUID().toString());
actualJson.put("id", 100);
actualJson.put("type", "foo");
actualJson.put("array", array);
actualJson.put("object", object);
System.out.println("-----actualJson------");
System.out.println(actualJson.toString(2));
}
JSONAssert.assertEquals(expectedJson.toString(2),
actualJson.toString(2),
new RegularExpressionComparator(JSONCompareMode.STRICT));
}
public static class RegularExpressionComparator extends DefaultComparator {
private static final RegularExpressionValueMatcher<Object> REGEX_VALUE_MATCHER = new RegularExpressionValueMatcher<>();
private final ValueMatcher<Object> matcher;
public RegularExpressionComparator(JSONCompareMode mode) {
super(mode);
this.matcher = (actual, expected) -> Objects.equals(actual, expected) ||
expected instanceof String && REGEX_VALUE_MATCHER.equal(actual, expected);
}
@Override
public void compareValues(String prefix, Object expectedValue, Object actualValue, JSONCompareResult result) throws JSONException {
if (actualValue instanceof JSONArray || actualValue instanceof JSONObject) {
super.compareValues(prefix, expectedValue, actualValue, result);
} else {
try {
if (!matcher.equal(actualValue, expectedValue)) {
result.fail(prefix, expectedValue, actualValue);
}
} catch (ValueMatcherException e) {
result.fail(prefix, e);
}
}
}
}
}
Il n'y a pas de problème avec juste la fonction standard, mais je voulais une implémentation qui "correspond à tous les éléments avec des expressions régulières" ...- Le JSON que vous attendez lors de la vérification du CORPS de réponse de l'API Web. Est préparé sous forme de fichier, et afin d'adopter un mécanisme qui compare les données de réponse réelles avec le JSON lu à partir du fichier de valeurs attendues, utilisez CustomComparator
dans chaque cas de test pour sélectionner l'élément cible. Je pensais que ce serait (un peu) difficile à spécifier, et je voulais pouvoir l'appliquer automatiquement en spécifiant une expression régulière dans le fichier de valeur attendue.
Recommended Posts