mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-21 21:08:03 +01:00
Adding a uniform configuration for all json/yaml mapper use cases: part 1
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2022 Signal Messenger, LLC
|
||||
* Copyright 2021 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
@@ -81,7 +81,7 @@ public class HCaptchaClient implements CaptchaClient {
|
||||
throw new IOException("hCaptcha http failure : " + response.statusCode());
|
||||
}
|
||||
|
||||
final HCaptchaResponse hCaptchaResponse = SystemMapper.getMapper()
|
||||
final HCaptchaResponse hCaptchaResponse = SystemMapper.jsonMapper()
|
||||
.readValue(response.body(), HCaptchaResponse.class);
|
||||
|
||||
logger.debug("received hCaptcha response: {}", hCaptchaResponse);
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.currency;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.textsecuregcm.util.SystemMapper;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.net.URI;
|
||||
@@ -13,6 +15,9 @@ import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.util.Map;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.textsecuregcm.util.SystemMapper;
|
||||
|
||||
public class CoinMarketCapClient {
|
||||
|
||||
@@ -64,7 +69,7 @@ public class CoinMarketCapClient {
|
||||
|
||||
@VisibleForTesting
|
||||
static CoinMarketCapResponse parseResponse(final String responseJson) throws JsonProcessingException {
|
||||
return SystemMapper.getMapper().readValue(responseJson, CoinMarketCapResponse.class);
|
||||
return SystemMapper.jsonMapper().readValue(responseJson, CoinMarketCapResponse.class);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.currency;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.whispersystems.textsecuregcm.util.SystemMapper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.net.URI;
|
||||
@@ -10,6 +13,7 @@ import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.util.Map;
|
||||
import org.whispersystems.textsecuregcm.util.SystemMapper;
|
||||
|
||||
public class FixerClient {
|
||||
|
||||
@@ -35,7 +39,7 @@ public class FixerClient {
|
||||
throw new FixerException("Bad response: " + response.statusCode() + " " + response.toString());
|
||||
}
|
||||
|
||||
FixerResponse parsedResponse = SystemMapper.getMapper().readValue(response.body(), FixerResponse.class);
|
||||
FixerResponse parsedResponse = SystemMapper.jsonMapper().readValue(response.body(), FixerResponse.class);
|
||||
|
||||
if (parsedResponse.success) return parsedResponse.rates;
|
||||
else throw new FixerException("Got failed response!");
|
||||
|
||||
@@ -12,7 +12,6 @@ import com.codahale.metrics.MetricRegistry;
|
||||
import com.codahale.metrics.SharedMetricRegistries;
|
||||
import com.codahale.metrics.Timer;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import org.slf4j.Logger;
|
||||
@@ -26,8 +25,6 @@ public class StaticRateLimiter implements RateLimiter {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(StaticRateLimiter.class);
|
||||
|
||||
private static final ObjectMapper MAPPER = SystemMapper.getMapper();
|
||||
|
||||
protected final String name;
|
||||
|
||||
private final RateLimiterConfig config;
|
||||
@@ -81,7 +78,7 @@ public class StaticRateLimiter implements RateLimiter {
|
||||
|
||||
private void setBucket(final String key, final LeakyBucket bucket) {
|
||||
try {
|
||||
final String serialized = bucket.serialize(MAPPER);
|
||||
final String serialized = bucket.serialize(SystemMapper.jsonMapper());
|
||||
cacheCluster.useCluster(connection -> connection.sync().setex(
|
||||
getBucketName(key),
|
||||
(int) Math.ceil((config.bucketSize() / config.leakRatePerMillis()) / 1000),
|
||||
@@ -96,7 +93,7 @@ public class StaticRateLimiter implements RateLimiter {
|
||||
final String serialized = cacheCluster.withCluster(connection -> connection.sync().get(getBucketName(key)));
|
||||
|
||||
if (serialized != null) {
|
||||
return LeakyBucket.fromSerialized(MAPPER, serialized);
|
||||
return LeakyBucket.fromSerialized(SystemMapper.jsonMapper(), serialized);
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
logger.warn("Deserialization error", e);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2022 Signal Messenger, LLC
|
||||
* Copyright 2013 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
@@ -106,7 +106,7 @@ public class PushLatencyManager {
|
||||
|
||||
void recordPushSent(final UUID accountUuid, final long deviceId, final boolean isVoip) {
|
||||
try {
|
||||
final String recordJson = SystemMapper.getMapper().writeValueAsString(
|
||||
final String recordJson = SystemMapper.jsonMapper().writeValueAsString(
|
||||
new PushRecord(Instant.now(clock), isVoip ? PushType.VOIP : PushType.STANDARD));
|
||||
|
||||
redisCluster.useCluster(connection ->
|
||||
@@ -159,7 +159,7 @@ public class PushLatencyManager {
|
||||
.thenApply(recordJson -> {
|
||||
if (StringUtils.isNotEmpty(recordJson)) {
|
||||
try {
|
||||
return SystemMapper.getMapper().readValue(recordJson, PushRecord.class);
|
||||
return SystemMapper.jsonMapper().readValue(recordJson, PushRecord.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -14,9 +14,6 @@ import io.micrometer.core.instrument.Metrics;
|
||||
import io.micrometer.core.instrument.Timer;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.time.Clock;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
@@ -271,7 +268,7 @@ public class Accounts extends AbstractDynamoDbStore {
|
||||
"#version", ATTR_VERSION))
|
||||
.expressionAttributeValues(Map.of(
|
||||
":number", numberAttr,
|
||||
":data", AttributeValues.fromByteArray(SystemMapper.getMapper().writeValueAsBytes(account)),
|
||||
":data", AttributeValues.fromByteArray(SystemMapper.jsonMapper().writeValueAsBytes(account)),
|
||||
":cds", AttributeValues.fromBool(account.shouldBeVisibleInDirectory()),
|
||||
":pni", pniAttr,
|
||||
":version", AttributeValues.fromInt(account.getVersion()),
|
||||
@@ -342,7 +339,7 @@ public class Accounts extends AbstractDynamoDbStore {
|
||||
.conditionExpression("#version = :version")
|
||||
.expressionAttributeNames(Map.of("#data", ATTR_ACCOUNT_DATA, "#version", ATTR_VERSION))
|
||||
.expressionAttributeValues(Map.of(
|
||||
":data", AttributeValues.fromByteArray(SystemMapper.getMapper().writeValueAsBytes(account)),
|
||||
":data", AttributeValues.fromByteArray(SystemMapper.jsonMapper().writeValueAsBytes(account)),
|
||||
":version", AttributeValues.fromInt(account.getVersion()),
|
||||
":version_increment", AttributeValues.fromInt(1)))
|
||||
.build())
|
||||
@@ -423,7 +420,7 @@ public class Accounts extends AbstractDynamoDbStore {
|
||||
"#username_hash", ATTR_USERNAME_HASH,
|
||||
"#version", ATTR_VERSION))
|
||||
.expressionAttributeValues(Map.of(
|
||||
":data", AttributeValues.fromByteArray(SystemMapper.getMapper().writeValueAsBytes(account)),
|
||||
":data", AttributeValues.fromByteArray(SystemMapper.jsonMapper().writeValueAsBytes(account)),
|
||||
":username_hash", AttributeValues.fromByteArray(usernameHash),
|
||||
":version", AttributeValues.fromInt(account.getVersion()),
|
||||
":version_increment", AttributeValues.fromInt(1)))
|
||||
@@ -478,7 +475,7 @@ public class Accounts extends AbstractDynamoDbStore {
|
||||
"#username_hash", ATTR_USERNAME_HASH,
|
||||
"#version", ATTR_VERSION))
|
||||
.expressionAttributeValues(Map.of(
|
||||
":data", AttributeValues.fromByteArray(SystemMapper.getMapper().writeValueAsBytes(account)),
|
||||
":data", AttributeValues.fromByteArray(SystemMapper.jsonMapper().writeValueAsBytes(account)),
|
||||
":version", AttributeValues.fromInt(account.getVersion()),
|
||||
":version_increment", AttributeValues.fromInt(1)))
|
||||
.build())
|
||||
@@ -523,7 +520,7 @@ public class Accounts extends AbstractDynamoDbStore {
|
||||
"#cds", ATTR_CANONICALLY_DISCOVERABLE,
|
||||
"#version", ATTR_VERSION));
|
||||
final Map<String, AttributeValue> attrValues = new HashMap<>(Map.of(
|
||||
":data", AttributeValues.fromByteArray(SystemMapper.getMapper().writeValueAsBytes(account)),
|
||||
":data", AttributeValues.fromByteArray(SystemMapper.jsonMapper().writeValueAsBytes(account)),
|
||||
":cds", AttributeValues.fromBool(account.shouldBeVisibleInDirectory()),
|
||||
":version", AttributeValues.fromInt(account.getVersion()),
|
||||
":version_increment", AttributeValues.fromInt(1)));
|
||||
@@ -720,7 +717,7 @@ public class Accounts extends AbstractDynamoDbStore {
|
||||
KEY_ACCOUNT_UUID, uuidAttr,
|
||||
ATTR_ACCOUNT_E164, numberAttr,
|
||||
ATTR_PNI_UUID, pniUuidAttr,
|
||||
ATTR_ACCOUNT_DATA, AttributeValues.fromByteArray(SystemMapper.getMapper().writeValueAsBytes(account)),
|
||||
ATTR_ACCOUNT_DATA, AttributeValues.fromByteArray(SystemMapper.jsonMapper().writeValueAsBytes(account)),
|
||||
ATTR_VERSION, AttributeValues.fromInt(account.getVersion()),
|
||||
ATTR_CANONICALLY_DISCOVERABLE, AttributeValues.fromBool(account.shouldBeVisibleInDirectory())));
|
||||
|
||||
@@ -842,7 +839,7 @@ public class Accounts extends AbstractDynamoDbStore {
|
||||
throw new RuntimeException("item missing values");
|
||||
}
|
||||
try {
|
||||
final Account account = SystemMapper.getMapper().readValue(item.get(ATTR_ACCOUNT_DATA).b().asByteArray(), Account.class);
|
||||
final Account account = SystemMapper.jsonMapper().readValue(item.get(ATTR_ACCOUNT_DATA).b().asByteArray(), Account.class);
|
||||
|
||||
final UUID accountIdentifier = UUIDUtil.fromByteBuffer(item.get(KEY_ACCOUNT_UUID).b().asByteBuffer());
|
||||
final UUID phoneNumberIdentifierFromAttribute = AttributeValues.getUUID(item, ATTR_PNI_UUID, null);
|
||||
|
||||
@@ -96,7 +96,7 @@ public class AccountsManager {
|
||||
private final RegistrationRecoveryPasswordsManager registrationRecoveryPasswordsManager;
|
||||
private final Clock clock;
|
||||
|
||||
private static final ObjectMapper mapper = SystemMapper.getMapper();
|
||||
private static final ObjectMapper mapper = SystemMapper.jsonMapper();
|
||||
|
||||
// An account that's used at least daily will get reset in the cache at least once per day when its "last seen"
|
||||
// timestamp updates; expiring entries after two days will help clear out "zombie" cache entries that are read
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.storage;
|
||||
|
||||
import static org.whispersystems.textsecuregcm.metrics.MetricsUtil.name;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import java.time.Duration;
|
||||
@@ -18,6 +19,7 @@ import javax.validation.Validation;
|
||||
import javax.validation.Validator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.textsecuregcm.util.SystemMapper;
|
||||
import org.whispersystems.textsecuregcm.util.Util;
|
||||
import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
|
||||
import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient;
|
||||
@@ -39,11 +41,6 @@ public class DynamicConfigurationManager<T> {
|
||||
private String configurationToken = null;
|
||||
private boolean initialized = false;
|
||||
|
||||
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(new YAMLFactory())
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||
.registerModule(new JavaTimeModule());
|
||||
|
||||
private static final Validator VALIDATOR = Validation.buildDefaultValidatorFactory().getValidator();
|
||||
|
||||
private static final String ERROR_COUNTER_NAME = name(DynamicConfigurationManager.class, "error");
|
||||
@@ -143,7 +140,7 @@ public class DynamicConfigurationManager<T> {
|
||||
@VisibleForTesting
|
||||
public static <T> Optional<T> parseConfiguration(final String configurationYaml, final Class<T> configurationClass)
|
||||
throws JsonProcessingException {
|
||||
final T configuration = OBJECT_MAPPER.readValue(configurationYaml, configurationClass);
|
||||
final T configuration = SystemMapper.yamlMapper().readValue(configurationYaml, configurationClass);
|
||||
final Set<ConstraintViolation<T>> violations = VALIDATOR.validate(configuration);
|
||||
|
||||
final Optional<T> maybeDynamicConfiguration;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 Signal Messenger, LLC
|
||||
* Copyright 2013 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
@@ -30,7 +30,7 @@ public class ProfilesManager {
|
||||
final FaultTolerantRedisCluster cacheCluster) {
|
||||
this.profiles = profiles;
|
||||
this.cacheCluster = cacheCluster;
|
||||
this.mapper = SystemMapper.getMapper();
|
||||
this.mapper = SystemMapper.jsonMapper();
|
||||
}
|
||||
|
||||
public void set(UUID uuid, VersionedProfile versionedProfile) {
|
||||
|
||||
@@ -84,7 +84,7 @@ public abstract class SerializedExpireableJsonDynamoStore<T> {
|
||||
final Map<String, AttributeValue> attributeValueMap = new HashMap<>(Map.of(
|
||||
KEY_KEY, AttributeValues.fromString(key),
|
||||
ATTR_SERIALIZED_VALUE,
|
||||
AttributeValues.fromString(SystemMapper.getMapper().writeValueAsString(v))));
|
||||
AttributeValues.fromString(SystemMapper.jsonMapper().writeValueAsString(v))));
|
||||
if (v instanceof Expireable ev) {
|
||||
attributeValueMap.put(ATTR_TTL, AttributeValues.fromLong(getExpirationTimestamp(ev)));
|
||||
}
|
||||
@@ -117,7 +117,7 @@ public abstract class SerializedExpireableJsonDynamoStore<T> {
|
||||
try {
|
||||
return response.hasItem()
|
||||
? filterMaybeExpiredValue(
|
||||
SystemMapper.getMapper()
|
||||
SystemMapper.jsonMapper()
|
||||
.readValue(response.item().get(ATTR_SERIALIZED_VALUE).s(), deserializationTargetClass))
|
||||
: Optional.empty();
|
||||
} catch (final JsonProcessingException e) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 Signal Messenger, LLC
|
||||
* Copyright 2013 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
@@ -58,7 +58,7 @@ public class VerificationCodeStore {
|
||||
.tableName(tableName)
|
||||
.item(Map.of(
|
||||
KEY_E164, AttributeValues.fromString(number),
|
||||
ATTR_STORED_CODE, AttributeValues.fromString(SystemMapper.getMapper().writeValueAsString(verificationCode)),
|
||||
ATTR_STORED_CODE, AttributeValues.fromString(SystemMapper.jsonMapper().writeValueAsString(verificationCode)),
|
||||
ATTR_TTL, AttributeValues.fromLong(getExpirationTimestamp(verificationCode))))
|
||||
.build());
|
||||
} catch (final JsonProcessingException e) {
|
||||
@@ -84,7 +84,7 @@ public class VerificationCodeStore {
|
||||
try {
|
||||
return response.hasItem()
|
||||
? filterMaybeExpiredCode(
|
||||
SystemMapper.getMapper().readValue(response.item().get(ATTR_STORED_CODE).s(), StoredVerificationCode.class))
|
||||
SystemMapper.jsonMapper().readValue(response.item().get(ATTR_STORED_CODE).s(), StoredVerificationCode.class))
|
||||
: Optional.empty();
|
||||
} catch (final JsonProcessingException e) {
|
||||
log.error("Failed to parse stored verification code", e);
|
||||
|
||||
@@ -19,7 +19,6 @@ import com.braintreegateway.TransactionSearchRequest;
|
||||
import com.braintreegateway.exceptions.BraintreeException;
|
||||
import com.braintreegateway.exceptions.NotFoundException;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
import java.util.Comparator;
|
||||
@@ -40,6 +39,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.textsecuregcm.configuration.CircuitBreakerConfiguration;
|
||||
import org.whispersystems.textsecuregcm.http.FaultTolerantHttpClient;
|
||||
import org.whispersystems.textsecuregcm.util.SystemMapper;
|
||||
|
||||
public class BraintreeManager implements SubscriptionProcessorManager {
|
||||
|
||||
@@ -374,7 +374,7 @@ public class BraintreeManager implements SubscriptionProcessorManager {
|
||||
private long getLevelForPlan(final Plan plan) {
|
||||
final BraintreePlanMetadata metadata;
|
||||
try {
|
||||
metadata = new ObjectMapper().readValue(plan.getDescription(), BraintreePlanMetadata.class);
|
||||
metadata = SystemMapper.jsonMapper().readValue(plan.getDescription(), BraintreePlanMetadata.class);
|
||||
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
@@ -477,7 +477,7 @@ public class BraintreeManager implements SubscriptionProcessorManager {
|
||||
|
||||
final BraintreePlanMetadata metadata;
|
||||
try {
|
||||
metadata = new ObjectMapper().readValue(plan.getDescription(), BraintreePlanMetadata.class);
|
||||
metadata = SystemMapper.jsonMapper().readValue(plan.getDescription(), BraintreePlanMetadata.class);
|
||||
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 Signal Messenger, LLC
|
||||
* Copyright 2013 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
@@ -7,28 +7,55 @@ package org.whispersystems.textsecuregcm.util;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.Module;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
|
||||
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import com.vdurmont.semver4j.Semver;
|
||||
import java.io.IOException;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class SystemMapper {
|
||||
|
||||
private static final ObjectMapper MAPPER = build();
|
||||
private static final ObjectMapper JSON_MAPPER = configureMapper(new ObjectMapper());
|
||||
|
||||
private static final ObjectMapper YAML_MAPPER = configureMapper(new YAMLMapper());
|
||||
|
||||
|
||||
@Nonnull
|
||||
public static ObjectMapper getMapper() {
|
||||
return MAPPER;
|
||||
public static ObjectMapper jsonMapper() {
|
||||
return JSON_MAPPER;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private static ObjectMapper build() {
|
||||
final ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
|
||||
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
|
||||
mapper.registerModule(new JavaTimeModule());
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
return mapper;
|
||||
public static ObjectMapper yamlMapper() {
|
||||
return YAML_MAPPER;
|
||||
}
|
||||
|
||||
public static ObjectMapper configureMapper(final ObjectMapper mapper) {
|
||||
return mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||
.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE)
|
||||
.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
|
||||
.registerModules(
|
||||
applicationModule(),
|
||||
new JavaTimeModule(),
|
||||
new Jdk8Module());
|
||||
}
|
||||
|
||||
private static Module applicationModule() {
|
||||
return new SimpleModule()
|
||||
.addDeserializer(Semver.class, new JsonDeserializer<>() {
|
||||
@Override
|
||||
public Semver deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException {
|
||||
final String strValue = p.readValueAs(String.class);
|
||||
return strValue != null ? new Semver(strValue) : null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user