Skip to content
This repository was archived by the owner on Oct 31, 2024. It is now read-only.
This repository was archived by the owner on Oct 31, 2024. It is now read-only.

gson support #29

Description

@wryun

May or may not work, too lazy to raise a PR, sorry - it's here in case someone wants it.

package io.atlassian.rps.util;

import java.util.List;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonArray;
import com.google.gson.JsonSyntaxException;

import io.burt.jmespath.BaseRuntime;
import io.burt.jmespath.JmesPathType;
import static io.burt.jmespath.JmesPathType.NULL;
import static io.burt.jmespath.JmesPathType.STRING;
import static io.burt.jmespath.JmesPathType.BOOLEAN;
import static io.burt.jmespath.JmesPathType.OBJECT;
import static io.burt.jmespath.JmesPathType.ARRAY;
import static io.burt.jmespath.JmesPathType.NUMBER;
import io.burt.jmespath.function.FunctionRegistry;

/**
 * Unfortunately, Jmespath supports only Jackson in the default library, so we have to
 * write our own adapter for Gson (cribbed off the Jackson one).
 */
public class JmespathGsonRuntime extends BaseRuntime<JsonElement> {
    private final Gson jsonParser;

    public JmespathGsonRuntime() {
        this(null);
    }

    public JmespathGsonRuntime(FunctionRegistry functionRegistry) {
        super(functionRegistry);
        this.jsonParser = new Gson();
    }

    @Override
    public JsonElement parseString(String string) {
        try {
            return jsonParser.fromJson(string, JsonElement.class);
        } catch (JsonSyntaxException e) {
            throw new IllegalStateException(e);
        }
    }

    @Override
    public List<JsonElement> toList(JsonElement value) {
        if (value.isJsonArray()) {
            return StreamSupport.stream(value.getAsJsonArray().spliterator(), false)
                    .collect(Collectors.toList());
        } else if (value.isJsonObject()) {
            return value.getAsJsonObject().entrySet().stream()
                    .map(Map.Entry::getValue)
                    .collect(Collectors.toList());
        } else {
            return Collections.emptyList();
        }
    }

    @Override
    public String toString(JsonElement str) {
        if (str.isJsonPrimitive()) {
            return str.getAsString();
        } else {
            return str.toString();
        }
    }

    @Override
    public Number toNumber(JsonElement n) {
        return n.getAsNumber();
    }

    @Override
    public boolean isTruthy(JsonElement value) {
        switch (typeOf(value)) {
        case NULL:
            return false;
        case BOOLEAN:
            return value.getAsBoolean();
        case STRING:
            return value.getAsString().length() > 0;
        case NUMBER:
            return value.getAsFloat() > 0;
        case ARRAY:
            return value.getAsJsonArray().size() > 0;
        case OBJECT:
            return value.getAsJsonObject().size() > 0;
        }

        throw new IllegalStateException(String.format("Unknown node type encountered: %s", value.getClass()));
    }

    @Override
    public JmesPathType typeOf(JsonElement value) {
        if (value.isJsonNull()) {
            return JmesPathType.NULL;
        } else if (value.isJsonArray()) {
            return JmesPathType.ARRAY;
        } else if (value.isJsonObject()) {
            return JmesPathType.OBJECT;
        } else if (value.isJsonPrimitive()) {
            JsonPrimitive primValue = value.getAsJsonPrimitive();
            if (primValue.isBoolean()) {
                return JmesPathType.BOOLEAN;
            } else if (primValue.isNumber()) {
                return JmesPathType.NUMBER;
            } else if (primValue.isString()) {
                return JmesPathType.STRING;
            }
        }

        throw new IllegalStateException(String.format("Unknown node type encountered: %s", value.getClass()));
    }

    @Override
    public JsonElement getProperty(JsonElement value, JsonElement name) {
        return nodeOrNullNode(
            value.isJsonObject() ? value.getAsJsonObject().get(name.getAsString()) : null
        );
    }

    @Override
    public Collection<JsonElement> getPropertyNames(JsonElement value) {
        if (value.isJsonObject()) {
            return value.getAsJsonObject().entrySet().stream()
                    .map(entry -> new JsonPrimitive(entry.getKey()))
                    .collect(Collectors.toList());
        } else {
            return Collections.emptyList();
        }
    }

    @Override
    public JsonElement createNull() {
        return nodeOrNullNode(null);
    }

    @Override
    public JsonElement createArray(Collection<JsonElement> elements) {
        JsonArray array = new JsonArray();
        elements.forEach(array::add);
        return array;
    }

    @Override
    public JsonElement createString(String str) {
        return new JsonPrimitive(str);
    }

    @Override
    public JsonElement createBoolean(boolean b) {
        return new JsonPrimitive(b);
    }

    @Override
    public JsonElement createObject(Map<JsonElement, JsonElement> obj) {
        JsonObject result = new JsonObject();
        obj.entrySet().forEach(entry -> result.add(entry.getKey().getAsString(), entry.getValue()));
        return result;
    }

    @Override
    public JsonElement createNumber(double n) {
        return new JsonPrimitive(n);
    }

    @Override
    public JsonElement createNumber(long n) {
        return new JsonPrimitive(n);
    }

    private JsonElement nodeOrNullNode(JsonElement node) {
        if (node == null) {
            return JsonNull.INSTANCE;
        } else {
            return node;
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions