public static TestConfig fromJson(byte[] jsonBytes) {
        Inspector config = SlimeUtils.jsonToSlime(jsonBytes).get();
        if (config.field("localEndpoints").valid())
            return TestConfig.fromEndpointsOnly(toClusterMap(config.field("localEndpoints")));

        ApplicationId application = ApplicationId.fromSerializedForm(config.field("application").asString());
        ZoneId zone = ZoneId.from(config.field("zone").asString());
        SystemName system = SystemName.from(config.field("system").asString());
        boolean isCI = config.field("isCI").asBool();
        String platform = config.field("platform").asString();
        long revision = config.field("revision").asLong();
        Instant deployedAt = Instant.ofEpochMilli(config.field("deployedAt").asLong());
        Map<ZoneId, Map<String, URI>> deployments = new HashMap<>();
        config.field("zoneEndpoints").traverse((ObjectTraverser) (zoneId, clustersObject) -> {
            deployments.put(ZoneId.from(zoneId), toClusterMap(clustersObject));
        });
        Map<ZoneId, List<String>> contentClusters = new HashMap<>();
        config.field("clusters").traverse(((ObjectTraverser) (zoneId, clustersArray) -> {
            List<String> clusters = new ArrayList<>();
            clustersArray.traverse((ArrayTraverser) (__, cluster) -> clusters.add(cluster.asString()));
            contentClusters.put(ZoneId.from(zoneId), clusters);
        }));
        return new TestConfig(application, zone, system, isCI, platform, revision, deployedAt, deployments, contentClusters);
    }
Parses the given test config JSON and returns a new config instance.

If the given JSON has a "localEndpoints" element, a config object with default values
is returned, using {@link #fromEndpointsOnly}. Otherwise, all config attributes are parsed.
hosted-api/src/main/java/ai/vespa/hosted/api/TestConfig.java