FriendFileLoader { public T load() throws IOException, FriendFileLoaderException { final Gson gson = gsonSupplier.get(); JsonObject rootObject = tryAsObject(new JsonParser().parse(new BufferedReader(new InputStreamReader(Files.newInputStream(this.readPath)))), "Root element of friends file must be a JSON object"); JsonObject boundsObject = tryAsObject(rootObject.get("bounds"), "Bounds element of friends file must be a JSON object"); Bounds bounds = gson.fromJson(boundsObject, Bounds.class); JsonArray listArray = tryAsArray(rootObject.get("list")); Set<S> persons = new HashSet<>(); for (JsonElement element : listArray) { persons.add(gson.fromJson(element, this.personClass)); } return this.factory.apply(bounds, persons); } private  FriendFileLoader(Class<S> personClass); static FriendFileLoader<T, S> loader(Class<S> personClass); static FriendFileLoader<Configuration<Person>, Person> defaultLoader(); FriendFileLoader<T, S> withFactory(BiFunction<Bounds, Set<S>, T> factory); FriendFileLoader<Configuration<S>, S> withDefaultFactory(); FriendFileLoader<T, S> withPath(Path path); FriendFileLoader<T, S> withDefaultPath(); FriendFileLoader<T, S> withGson(Supplier<Gson> gsonSupplier); T load();  }
@Test @DisplayName("Default loader works") void load() throws URISyntaxException, IOException, FriendFileLoaderException { FriendFileLoader<Configuration<Person>, Person> loader = FriendFileLoader.defaultLoader() .withPath(TestUtil.getPath("friends.json")); assertDoesNotThrow((Executable) loader::load, "Loads without exceptions"); Configuration<Person> configuration = loader.load(); Set<Person> set = configuration.getFriendList(); assertEquals(1, set.size(), "One person was loaded"); Person person = set.stream().findAny().get(); assertEquals("foo", person.getName()); assertEquals("8a2a3ef5-8d27-41b9-a69a-cbb05ac0ed1d", person.getId().toString()); assertEquals(0, person.getValue()); JsonObject meta = person.getMeta(); assertTrue(meta.has("displayName"), "Meta has displayName"); assertEquals("bar", meta.get("displayName").getAsString()); }