#include "json_element.hpp" #include "json_array.hpp" #include "json_object.hpp" #include "json_primitive.hpp" #include "../math/math.hpp" namespace mbgl { namespace android { namespace gson { jni::Local> JsonElement::New(jni::JNIEnv& env, const mbgl::Value& value) { static auto& primitive = jni::Class::Singleton(env); static auto stringConstructor = primitive.GetConstructor(env); static auto numberConstructor = primitive.GetConstructor(env); static auto booleanConstructor = primitive.GetConstructor(env); return value.match( [&] (const mbgl::NullValue&) { return jni::Local>(); }, [&] (const std::string& value) { return primitive.New(env, stringConstructor, jni::Make(env, value)); }, [&] (const double value) { return primitive.New(env, numberConstructor, jni::Box(env, value)); }, [&] (const int64_t value) { return primitive.New(env, numberConstructor, jni::Box(env, value)); }, [&] (const uint64_t value) { return primitive.New(env, numberConstructor, jni::Box(env, int64_t(value))); // TODO: should use BigInteger }, [&] (const bool value) { return primitive.New(env, booleanConstructor, jni::Box(env, value ? jni::jni_true : jni::jni_false)); }, [&] (const std::vector& values) { return JsonArray::New(env, values); }, [&] (const mbgl::PropertyMap& values) { return JsonObject::New(env, values); } ); } mbgl::Value JsonElement::convert(jni::JNIEnv &env, const jni::Object& jsonElement) { if (!jsonElement) { return mbgl::NullValue(); } static auto& elementClass = jni::Class::Singleton(env); static auto isJsonObject = elementClass.GetMethod(env, "isJsonObject"); static auto isJsonArray = elementClass.GetMethod(env, "isJsonArray"); static auto isJsonPrimitive = elementClass.GetMethod(env, "isJsonPrimitive"); static auto& primitiveClass = jni::Class::Singleton(env); static auto isBoolean = primitiveClass.GetMethod(env, "isBoolean"); static auto isString = primitiveClass.GetMethod(env, "isString"); static auto isNumber = primitiveClass.GetMethod(env, "isNumber"); static auto getAsBoolean = primitiveClass.GetMethod(env, "getAsBoolean"); static auto getAsString = primitiveClass.GetMethod(env, "getAsString"); static auto getAsDouble = primitiveClass.GetMethod(env, "getAsDouble"); static auto getAsInteger = primitiveClass.GetMethod(env, "getAsInt"); if (jsonElement.Call(env, isJsonPrimitive)) { auto primitive = jni::Cast(env, primitiveClass, jsonElement); if (primitive.Call(env, isBoolean)) { return bool(primitive.Call(env, getAsBoolean)); } else if (primitive.Call(env, isNumber)) { auto value = primitive.Call(env, getAsDouble); if (value == math::Math::rint(env, value)) { // uint64_t return static_cast(primitive.Call(env, getAsInteger)); } else { // double return value; } } else if (primitive.Call(env, isString)) { return jni::Make(env, primitive.Call(env, getAsString)); } else { return mbgl::NullValue(); } } else if (jsonElement.Call(env, isJsonObject)) { return JsonObject::convert(env, jni::Cast(env, jni::Class::Singleton(env), jsonElement)); } else if (jsonElement.Call(env, isJsonArray)) { return JsonArray::convert(env, jni::Cast(env, jni::Class::Singleton(env), jsonElement)); } else { return mbgl::NullValue(); } } void JsonElement::registerNative(jni::JNIEnv &env) { jni::Class::Singleton(env); } } // namespace gson } // namespace android } // namespace mbgl