class ImmutableMeasurement implements Measurement {

    public static Measurement fromJson(final JsonObject jsonObject) {

        final JsonField type = unwrap(jsonObject);
        final JsonField success = unwrap(type.getValue());
        final JsonObject counterJson = success.getValue().asObject();

        final Map<Duration, Long> readCounterMap =
                counterJson.stream()
                        .filter(f -> f.getValue().isNumber())
                        .collect(Collectors.toMap(f -> Duration.parse(f.getKeyName()), f -> f.getValue().asLong()));

        final Instant readLastMessageAt = counterJson
                .getValue(JsonFields.LAST_MESSAGE_AT)
                .map(Instant::parse)
                .orElse(null);

        return new ImmutableMeasurement(MetricType.forName(type.getKeyName())
                .orElseThrow(() -> JsonParseException.newBuilder()
                        .message("Unknown metricType: '" + type.getKeyName() + "'")
                        .build()
                ),
                fromSuccessFieldName(success.getKeyName()), readCounterMap,
                readLastMessageAt);
    }

      ImmutableMeasurement(final MetricType metricType, final boolean success,
            final Map<Duration, Long> values, @Nullable final Instant lastMessageAt);

}