package com.auth0.jwt.impl;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.Claim;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* The JsonNodeClaim retrieves a claim value from a JsonNode object.
*/
class JsonNodeClaim implements Claim {
private final JsonNode data;
private JsonNodeClaim(JsonNode node) {
this.data = node;
}
@Override
public Boolean asBoolean() {
return !data.isBoolean() ? null : data.asBoolean();
}
@Override
public Integer asInt() {
return !data.isNumber() ? null : data.asInt();
}
@Override
public Long asLong() {
return !data.isNumber() ? null : data.asLong();
}
@Override
public Double asDouble() {
return !data.isNumber() ? null : data.asDouble();
}
@Override
public String asString() {
return !data.isTextual() ? null : data.asText();
}
@Override
public Date asDate() {
if (!data.canConvertToLong()) {
return null;
}
long seconds = data.asLong();
return new Date(seconds * 1000);
}
@Override
@SuppressWarnings("unchecked")
public <T> T[] asArray(Class<T> tClazz) throws JWTDecodeException {
if (!data.isArray()) {
return null;
}
ObjectMapper mapper = new ObjectMapper();
T[] arr = (T[]) Array.newInstance(tClazz, data.size());
for (int i = 0; i < data.size(); i++) {
try {
arr[i] = mapper.treeToValue(data.get(i), tClazz);
} catch (JsonProcessingException e) {
throw new JWTDecodeException("Couldn't map the Claim's array contents to " + tClazz.getSimpleName(), e);
}
}
return arr;
}
@Override
public <T> List<T> asList(Class<T> tClazz) throws JWTDecodeException {
if (!data.isArray()) {
return null;
}
ObjectMapper mapper = new ObjectMapper();
List<T> list = new ArrayList<>();
for (int i = 0; i < data.size(); i++) {
try {
list.add(mapper.treeToValue(data.get(i), tClazz));
} catch (JsonProcessingException e) {
throw new JWTDecodeException("Couldn't map the Claim's array contents to " + tClazz.getSimpleName(), e);
}
}
return list;
}
@Override
public Map<String, Object> asMap() throws JWTDecodeException {
if (!data.isObject()) {
return null;
}
ObjectMapper mapper = new ObjectMapper();
try {
TypeReference<Map<String, Object>> mapType = new TypeReference<Map<String, Object>>() {
};
return mapper.treeAsTokens(data).readValueAs(mapType);
} catch (IOException e) {
throw new JWTDecodeException("Couldn't map the Claim value to Map", e);
}
}
@Override
public <T> T as(Class<T> tClazz) throws JWTDecodeException {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.treeAsTokens(data).readValueAs(tClazz);
} catch (IOException e) {
throw new JWTDecodeException("Couldn't map the Claim value to " + tClazz.getSimpleName(), e);
}
}
@Override
public boolean isNull() {
return false;
}
/**
* Helper method to extract a Claim from the given JsonNode tree.
*
* @param claimName the Claim to search for.
* @param tree the JsonNode tree to search the Claim in.
* @return a valid non-null Claim.
*/
static Claim extractClaim(String claimName, Map<String, JsonNode> tree) {
JsonNode node = tree.get(claimName);
return claimFromNode(node);
}
/**
* Helper method to create a Claim representation from the given JsonNode.
*
* @param node the JsonNode to convert into a Claim.
* @return a valid Claim instance. If the node is null or missing, a NullClaim will be returned.
*/
static Claim claimFromNode(JsonNode node) {
if (node == null || node.isNull() || node.isMissingNode()) {
return new NullClaim();
}
return new JsonNodeClaim(node);
}
}