import java.lang.reflect.Array;
import java.util.*;
class JsonStructureValidator {
public static boolean isValidJson
(Object input
) { Set
<Object
> seen
= Collections.
newSetFromMap(new IdentityHashMap
<>()); return isValidJsonImpl(input, seen);
}
private static boolean isValidJsonImpl
(Object input, Set
<Object
> seen
) { if (input == null) return true;
if (isPrimitiveAllowed(input)) return true;
if (input
instanceof Map) { if (!seen.add(input)) return false;
Map<?, ?> map = (Map<?, ?>) input;
for (Map.
Entry<?,
?> e
: map.
entrySet()) {
if (!(key
instanceof String)) { seen.remove(input);
return false;
}
if (!isValidJsonImpl(value, seen)) {
seen.remove(input);
return false;
}
}
seen.remove(input);
return true;
}
if (input
instanceof List) { if (!seen.add(input)) return false;
List<?> list = (List<?>) input;
if (!isValidJsonImpl(item, seen)) {
seen.remove(input);
return false;
}
}
seen.remove(input);
return true;
}
if (input.getClass().isArray()) {
if (!seen.add(input)) return false;
int len
= Array.
getLength(input
); for (int i = 0; i < len; i++) {
if (!isValidJsonImpl(elem, seen)) {
seen.remove(input);
return false;
}
}
seen.remove(input);
return true;
}
return false;
}
private static boolean isPrimitiveAllowed
(Object input
) { return input
instanceof String }
public static void main
(String[] args
) { Map
<String, Object
> valid
= Map.
of("user",
Map.
of("name",
"A",
"age",
30)); System.
out.
println(isValidJson
(valid
)); // true
Map
<String, Object
> m2
= new HashMap
<>(); m2.
put("tags",
List.
of("x",
"y")); m2.put("scores", new int[] {1, 2, 3});
System.
out.
println(isValidJson
(m2
)); // true
Map
<Object, Object
> wrongKey
= new HashMap
<>(); wrongKey.put(123, "numberAsKey");
System.
out.
println(isValidJson
(wrongKey
)); // false
Map
<String, Object
> withSet
= new HashMap
<>(); withSet.
put("s",
Set.
of("a",
"b")); System.
out.
println(isValidJson
(withSet
)); // false
}
}
aW1wb3J0IGphdmEubGFuZy5yZWZsZWN0LkFycmF5OwppbXBvcnQgamF2YS51dGlsLio7CgpjbGFzcyBKc29uU3RydWN0dXJlVmFsaWRhdG9yIHsKCiAgICBwdWJsaWMgc3RhdGljIGJvb2xlYW4gaXNWYWxpZEpzb24oT2JqZWN0IGlucHV0KSB7CiAgICAgICAgU2V0PE9iamVjdD4gc2VlbiA9IENvbGxlY3Rpb25zLm5ld1NldEZyb21NYXAobmV3IElkZW50aXR5SGFzaE1hcDw+KCkpOwogICAgICAgIHJldHVybiBpc1ZhbGlkSnNvbkltcGwoaW5wdXQsIHNlZW4pOwogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIGJvb2xlYW4gaXNWYWxpZEpzb25JbXBsKE9iamVjdCBpbnB1dCwgU2V0PE9iamVjdD4gc2VlbikgewogICAgICAgIGlmIChpbnB1dCA9PSBudWxsKSByZXR1cm4gdHJ1ZTsKCiAgICAgICAgaWYgKGlzUHJpbWl0aXZlQWxsb3dlZChpbnB1dCkpIHJldHVybiB0cnVlOwoKICAgICAgICBpZiAoaW5wdXQgaW5zdGFuY2VvZiBNYXApIHsKICAgICAgICAgICAgaWYgKCFzZWVuLmFkZChpbnB1dCkpIHJldHVybiBmYWxzZTsKCiAgICAgICAgICAgIE1hcDw/LCA/PiBtYXAgPSAoTWFwPD8sID8+KSBpbnB1dDsKICAgICAgICAgICAgZm9yIChNYXAuRW50cnk8PywgPz4gZSA6IG1hcC5lbnRyeVNldCgpKSB7CiAgICAgICAgICAgICAgICBPYmplY3Qga2V5ID0gZS5nZXRLZXkoKTsKICAgICAgICAgICAgICAgIE9iamVjdCB2YWx1ZSA9IGUuZ2V0VmFsdWUoKTsKCiAgICAgICAgICAgICAgICBpZiAoIShrZXkgaW5zdGFuY2VvZiBTdHJpbmcpKSB7CiAgICAgICAgICAgICAgICAgICAgc2Vlbi5yZW1vdmUoaW5wdXQpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICBpZiAoIWlzVmFsaWRKc29uSW1wbCh2YWx1ZSwgc2VlbikpIHsKICAgICAgICAgICAgICAgICAgICBzZWVuLnJlbW92ZShpbnB1dCk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHNlZW4ucmVtb3ZlKGlucHV0KTsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQoKICAgICAgICBpZiAoaW5wdXQgaW5zdGFuY2VvZiBMaXN0KSB7CiAgICAgICAgICAgIGlmICghc2Vlbi5hZGQoaW5wdXQpKSByZXR1cm4gZmFsc2U7CgogICAgICAgICAgICBMaXN0PD8+IGxpc3QgPSAoTGlzdDw/PikgaW5wdXQ7CiAgICAgICAgICAgIGZvciAoT2JqZWN0IGl0ZW0gOiBsaXN0KSB7CiAgICAgICAgICAgICAgICBpZiAoIWlzVmFsaWRKc29uSW1wbChpdGVtLCBzZWVuKSkgewogICAgICAgICAgICAgICAgICAgIHNlZW4ucmVtb3ZlKGlucHV0KTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgc2Vlbi5yZW1vdmUoaW5wdXQpOwogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CgogICAgICAgIGlmIChpbnB1dC5nZXRDbGFzcygpLmlzQXJyYXkoKSkgewogICAgICAgICAgICBpZiAoIXNlZW4uYWRkKGlucHV0KSkgcmV0dXJuIGZhbHNlOwoKICAgICAgICAgICAgaW50IGxlbiA9IEFycmF5LmdldExlbmd0aChpbnB1dCk7CiAgICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbGVuOyBpKyspIHsKICAgICAgICAgICAgICAgIE9iamVjdCBlbGVtID0gQXJyYXkuZ2V0KGlucHV0LCBpKTsKICAgICAgICAgICAgICAgIGlmICghaXNWYWxpZEpzb25JbXBsKGVsZW0sIHNlZW4pKSB7CiAgICAgICAgICAgICAgICAgICAgc2Vlbi5yZW1vdmUoaW5wdXQpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBzZWVuLnJlbW92ZShpbnB1dCk7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIGJvb2xlYW4gaXNQcmltaXRpdmVBbGxvd2VkKE9iamVjdCBpbnB1dCkgewogICAgICAgIHJldHVybiBpbnB1dCBpbnN0YW5jZW9mIFN0cmluZwogICAgICAgICAgICAgICAgfHwgaW5wdXQgaW5zdGFuY2VvZiBOdW1iZXIKICAgICAgICAgICAgICAgIHx8IGlucHV0IGluc3RhbmNlb2YgQm9vbGVhbjsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSB7CiAgICAgICAgTWFwPFN0cmluZywgT2JqZWN0PiB2YWxpZCA9IE1hcC5vZigidXNlciIsIE1hcC5vZigibmFtZSIsICJBIiwgImFnZSIsIDMwKSk7CiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKGlzVmFsaWRKc29uKHZhbGlkKSk7IC8vIHRydWUKCiAgICAgICAgTWFwPFN0cmluZywgT2JqZWN0PiBtMiA9IG5ldyBIYXNoTWFwPD4oKTsKICAgICAgICBtMi5wdXQoInRhZ3MiLCBMaXN0Lm9mKCJ4IiwgInkiKSk7CiAgICAgICAgbTIucHV0KCJzY29yZXMiLCBuZXcgaW50W10gezEsIDIsIDN9KTsKICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oaXNWYWxpZEpzb24obTIpKTsgLy8gdHJ1ZQoKICAgICAgICBNYXA8T2JqZWN0LCBPYmplY3Q+IHdyb25nS2V5ID0gbmV3IEhhc2hNYXA8PigpOwogICAgICAgIHdyb25nS2V5LnB1dCgxMjMsICJudW1iZXJBc0tleSIpOwogICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbihpc1ZhbGlkSnNvbih3cm9uZ0tleSkpOyAvLyBmYWxzZQoKICAgICAgICBNYXA8U3RyaW5nLCBPYmplY3Q+IHdpdGhTZXQgPSBuZXcgSGFzaE1hcDw+KCk7CiAgICAgICAgd2l0aFNldC5wdXQoInMiLCBTZXQub2YoImEiLCAiYiIpKTsKICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oaXNWYWxpZEpzb24od2l0aFNldCkpOyAvLyBmYWxzZQoKICAgIH0KfQo=