Exemple #1
0
static void
log_json_parser_process_single (struct json_object *jso,
                                const gchar *prefix,
                                const gchar *obj_key,
                                LogMessage *msg)
{
  SBGString *key, *value;
  gboolean parsed = FALSE;

  key = sb_gstring_acquire ();
  value = sb_gstring_acquire ();

  switch (json_object_get_type (jso))
    {
    case json_type_boolean:
      parsed = TRUE;
      if (json_object_get_boolean (jso))
        g_string_assign (sb_gstring_string (value), "true");
      else
        g_string_assign (sb_gstring_string (value), "false");
      break;
    case json_type_double:
      parsed = TRUE;
      g_string_printf (sb_gstring_string (value), "%f",
                       json_object_get_double (jso));
      break;
    case json_type_int:
      parsed = TRUE;
      g_string_printf (sb_gstring_string (value), "%i",
                       json_object_get_int (jso));
      break;
    case json_type_string:
      parsed = TRUE;
      g_string_assign (sb_gstring_string (value),
                       json_object_get_string (jso));
      break;
    case json_type_object:
      if (prefix)
        g_string_assign (sb_gstring_string (key), prefix);
      g_string_append (sb_gstring_string (key), obj_key);
      g_string_append_c (sb_gstring_string (key), '.');
      log_json_parser_process_object (jso, sb_gstring_string (key)->str, msg);
      break;
    case json_type_array:
      {
        gint i, plen;

        g_string_assign (sb_gstring_string (key), obj_key);

        plen = sb_gstring_string (key)->len;

        for (i = 0; i < json_object_array_length (jso); i++)
          {
            g_string_truncate (sb_gstring_string (key), plen);
            g_string_append_printf (sb_gstring_string (key), "[%d]", i);
            log_json_parser_process_single (json_object_array_get_idx (jso, i),
                                            prefix,
                                            sb_gstring_string (key)->str, msg);
          }
        break;
      }
    case json_type_null:
      break;
    default:
      msg_error ("JSON parser encountered an unknown type, skipping",
                 evt_tag_str ("key", obj_key), NULL);
      break;
    }

  if (parsed)
    {
      if (prefix)
        {
          g_string_assign (sb_gstring_string (key), prefix);
          g_string_append (sb_gstring_string (key), obj_key);
          log_msg_set_value (msg,
                             log_msg_get_value_handle (sb_gstring_string (key)->str),
                             sb_gstring_string (value)->str,
                             sb_gstring_string (value)->len);
        }
      else
        log_msg_set_value (msg,
                           log_msg_get_value_handle (obj_key),
                           sb_gstring_string (value)->str,
                           sb_gstring_string (value)->len);
    }

  sb_gstring_release (key);
  sb_gstring_release (value);
}
Exemple #2
0
bool JsonToBsonAppendElement(BSON *bb , const char *k , struct json_object *v )
{
	bool status;

	status = true;
	if (!v)
	{
		BsonAppendNull(bb, k);
		return status;
	}

	switch (json_object_get_type(v))
	{
		case json_type_int:
		BsonAppendInt32(bb, k, json_object_get_int(v));
		break;

		case json_type_boolean:
		BsonAppendBool(bb , k, json_object_get_boolean(v));
		break;

		case json_type_double:
		BsonAppendDouble(bb, k, json_object_get_double(v));
		break;

		case json_type_string:
		BsonAppendUTF8(bb, k, (char*)json_object_get_string(v));
		break;

		case json_type_object:
		{
			BSON t;
			struct json_object *joj = NULL;
			joj = json_object_object_get(v, "$oid");

			if (joj != NULL)
			{
				bson_oid_t bsonObjectId;
				memset(bsonObjectId.bytes, 0, sizeof(bsonObjectId.bytes));
				BsonOidFromString(&bsonObjectId, (char*)json_object_get_string(joj));
				status = BsonAppendOid(bb, k , &bsonObjectId);
				break;
			}
			joj = json_object_object_get( v, "$date" );
			if (joj != NULL)
			{
				status = BsonAppendDate(bb, k, json_object_get_int64(joj));
				break;
			}
			BsonAppendStartObject(bb , (char*)k, &t);
			json_object_object_foreach(v, kk, vv)
			{
				JsonToBsonAppendElement(&t, kk, vv);
			}
			BsonAppendFinishObject(bb, &t);
			break;
		}
		case json_type_array:
		{
			int i;
			char buf[10];
			BSON t;
			BsonAppendStartArray(bb ,k, &t);
			for (i = 0; i<json_object_array_length(v); i++)
			{
				sprintf(buf , "%d" , i);
				JsonToBsonAppendElement(&t ,buf ,json_object_array_get_idx(v, i));
			}
			BsonAppendFinishObject( bb, &t );
			break;
		}
		default:
			ereport(ERROR, (errcode(ERRCODE_FDW_INVALID_DATA_TYPE),
			errmsg("can't handle type for : %s", json_object_to_json_string(v))));
	}
Exemple #3
0
/**
 * @ingroup VuoTransform
 * Decodes the JSON object @c js to create a new value.
 *
 * @eg{"identity"}
 * @eg{
 *   {
 *     "quaternionRotation" = [0,0,0,1],
 *     "translation" = [0,0,0],
 *     "scale" = [1,1,1]
 *   }
 * }
 * @eg{
 *   {
 *     "eulerRotation" = [0,0,0],
 *     "translation" = [0,0,0],
 *     "scale" = [1,1,1]
 *   }
 * }
 */
VuoTransform VuoTransform_valueFromJson(json_object *js)
{
	VuoTransform t = VuoTransform_makeIdentity();
	json_object *o = NULL;

	if (json_object_object_get_ex(js, "target", &o))
	{
		VuoPoint3d target;
		target.x = json_object_get_double(json_object_array_get_idx(o,0));
		target.y = json_object_get_double(json_object_array_get_idx(o,1));
		target.z = json_object_get_double(json_object_array_get_idx(o,2));

		VuoPoint3d position = VuoPoint3d_make(0,0,0);
		if (json_object_object_get_ex(js, "translation", &o))
		{
			position.x = json_object_get_double(json_object_array_get_idx(o,0));
			position.y = json_object_get_double(json_object_array_get_idx(o,1));
			position.z = json_object_get_double(json_object_array_get_idx(o,2));
		}

		VuoPoint3d upDirection = VuoPoint3d_make(0,1,0);
		if (json_object_object_get_ex(js, "upDirection", &o))
		{
			upDirection.x = json_object_get_double(json_object_array_get_idx(o,0));
			upDirection.y = json_object_get_double(json_object_array_get_idx(o,1));
			upDirection.z = json_object_get_double(json_object_array_get_idx(o,2));
		}

		return VuoTransform_makeFromTarget(position, target, upDirection);
	}

	if (json_object_object_get_ex(js, "quaternionRotation", &o))
	{
		t.type = VuoTransformTypeQuaternion;
		VuoPoint4d q;
		q.x = json_object_get_double(json_object_array_get_idx(o,0));
		q.y = json_object_get_double(json_object_array_get_idx(o,1));
		q.z = json_object_get_double(json_object_array_get_idx(o,2));
		q.w = json_object_get_double(json_object_array_get_idx(o,3));
		t = VuoTransform_makeQuaternion(VuoPoint3d_make(0,0,0), q, VuoPoint3d_make(0,0,0));
	}
	else if (json_object_object_get_ex(js, "eulerRotation", &o))
	{
		t.type = VuoTransformTypeEuler;
		VuoPoint3d e;
		e.x = json_object_get_double(json_object_array_get_idx(o,0));
		e.y = json_object_get_double(json_object_array_get_idx(o,1));
		e.z = json_object_get_double(json_object_array_get_idx(o,2));
		t = VuoTransform_makeEuler(VuoPoint3d_make(0,0,0), e, VuoPoint3d_make(0,0,0));
	}

	if (json_object_object_get_ex(js, "translation", &o))
	{
		t.translation.x = json_object_get_double(json_object_array_get_idx(o,0));
		t.translation.y = json_object_get_double(json_object_array_get_idx(o,1));
		t.translation.z = json_object_get_double(json_object_array_get_idx(o,2));
	}

	if (json_object_object_get_ex(js, "scale", &o))
	{
		t.scale.x = json_object_get_double(json_object_array_get_idx(o,0));
		t.scale.y = json_object_get_double(json_object_array_get_idx(o,1));
		t.scale.z = json_object_get_double(json_object_array_get_idx(o,2));
	}

	return t;
}
static int
populate_stats_from_resmon_formatted_json(noit_check_t *check,
                                          stats_t *s, struct json_object *o,
                                          const char *prefix) {
  int count = 0;
  char keybuff[256];
#define MKKEY(fmt, arg) do { \
  if(prefix) snprintf(keybuff, sizeof(keybuff), "%s`" fmt, prefix, arg); \
  else snprintf(keybuff, sizeof(keybuff), fmt, arg); \
} while(0)
  if(o == NULL) {
    if(prefix) {
      noit_stats_set_metric(check, s, prefix, METRIC_STRING, NULL);
      count++;
    }
    return count;
  }
  switch(json_object_get_type(o)) {
    /* sub callers */
    case json_type_array:
    {
      int i, alen = json_object_array_length(o);
      for(i=0;i<alen;i++) {
        struct json_object *item = json_object_array_get_idx(o, i);
        MKKEY("%d", i);
        count += populate_stats_from_resmon_formatted_json(check, s, item, keybuff);
      }
    }
    break;
    case json_type_object:
    {
      struct jl_lh_table *lh;
      struct jl_lh_entry *el;
      struct json_object *has_type = NULL, *has_value = NULL;
      lh = json_object_get_object(o);
      jl_lh_foreach(lh, el) {
        if(!strcmp(el->k, "_type")) has_type = (struct json_object *)el->v;
        else if(!strcmp(el->k, "_value")) has_value = (struct json_object *)el->v;
        else {
          struct json_object *item = (struct json_object *)el->v;
          MKKEY("%s", (const char *)el->k);
          count += populate_stats_from_resmon_formatted_json(check, s, item, keybuff);
        }
      }
      if(prefix && has_type && has_value &&
         json_object_is_type(has_type, json_type_string)) {
        const char *type_str = json_object_get_string(has_type);

#define COERCE_JSON_OBJECT(type, item) do { \
  const char *value_str = NULL; \
  if(json_object_is_type(item, json_type_string)) \
    value_str = json_object_get_string(item); \
  else if(!json_object_is_type(item, json_type_null)) \
    value_str = json_object_to_json_string(item); \
  switch(type) { \
    case METRIC_INT32: case METRIC_UINT32: case METRIC_INT64: \
    case METRIC_UINT64: case METRIC_DOUBLE: case METRIC_STRING: \
      noit_stats_set_metric_coerce(check, s, prefix, \
                                   (metric_type_t)type, value_str); \
      count++; \
    default: \
      break; \
  } \
} while(0)

        if(json_object_is_type(has_value, json_type_array)) {
          int i, alen = json_object_array_length(has_value);
          for(i=0;i<alen;i++) {
            struct json_object *item = json_object_array_get_idx(has_value, i);
            COERCE_JSON_OBJECT(*type_str, item);
          }
        }
        else {
          COERCE_JSON_OBJECT(*type_str, has_value);
        }
      }
      break;
    }

    /* directs */
    case json_type_string:
      if(prefix) {
        noit_stats_set_metric(check, s, prefix, METRIC_GUESS,
                              (char *)json_object_get_string(o));
        count++;
      }
      break;
    case json_type_boolean:
      if(prefix) {
        int val = json_object_get_boolean(o) ? 1 : 0;
        noit_stats_set_metric(check, s, prefix, METRIC_INT32, &val);
        count++;
      }
      break;
    case json_type_null:
      if(prefix) {
        noit_stats_set_metric(check, s, prefix, METRIC_STRING, NULL);
        count++;
      }
      break;
    case json_type_double:
      if(prefix) {
        double val = json_object_get_double(o);
        noit_stats_set_metric(check, s, prefix, METRIC_DOUBLE, &val);
        count++;
      }
      break;
    case json_type_int:
      if(prefix) {
        int64_t i64;
        uint64_t u64;
        switch(json_object_get_int_overflow(o)) {
          case json_overflow_int:
            i64 = json_object_get_int(o);
            noit_stats_set_metric(check, s, prefix, METRIC_INT64, &i64);
            count++;
            break;
          case json_overflow_int64:
            i64 = json_object_get_int64(o);
            noit_stats_set_metric(check, s, prefix, METRIC_INT64, &i64);
            count++;
            break;
          case json_overflow_uint64:
            u64 = json_object_get_uint64(o);
            noit_stats_set_metric(check, s, prefix, METRIC_UINT64, &u64);
            count++;
            break;
        }
      }
  }
  return count;
}
Exemple #5
0
void na_conf_env_init(struct json_object *environments_obj, na_env_t *na_env,
                      int idx, bool reconf)
{
    char *e;
    char host_buf[NA_HOSTNAME_MAX + 1];
    na_host_t host;
    struct json_object *environment_obj;
    struct json_object *param_obj;

    environment_obj = json_object_array_get_idx(environments_obj, idx);

    for (int i=0;i<NA_PARAM_MAX;++i) {
        double slow_query_sec;

        param_obj = json_object_object_get(environment_obj, na_param_name(i));

        if (param_obj == NULL) {
            continue;
        }

        // runtime-reconfigurable parameters
        switch (i) {
        case NA_PARAM_IS_CONNPOOL_ONLY:
            NA_PARAM_TYPE_CHECK(param_obj, json_type_boolean);
            na_env->is_connpool_only = json_object_get_boolean(param_obj) == 1 ? true : false;
            continue;
        case NA_PARAM_REQUEST_BUFSIZE:
            NA_PARAM_TYPE_CHECK(param_obj, json_type_int);
            na_env->request_bufsize = json_object_get_int(param_obj);
            continue;
        case NA_PARAM_REQUEST_BUFSIZE_MAX:
            NA_PARAM_TYPE_CHECK(param_obj, json_type_int);
            na_env->request_bufsize_max = json_object_get_int(param_obj);
            continue;
        case NA_PARAM_RESPONSE_BUFSIZE:
            NA_PARAM_TYPE_CHECK(param_obj, json_type_int);
            na_env->response_bufsize = json_object_get_int(param_obj);
            continue;
        case NA_PARAM_RESPONSE_BUFSIZE_MAX:
            NA_PARAM_TYPE_CHECK(param_obj, json_type_int);
            na_env->response_bufsize_max = json_object_get_int(param_obj);
            continue;
        case NA_PARAM_CONN_MAX:
            NA_PARAM_TYPE_CHECK(param_obj, json_type_int);
            na_env->conn_max = json_object_get_int(param_obj);
            continue;
        case NA_PARAM_ERROR_COUNT_MAX:
            NA_PARAM_TYPE_CHECK(param_obj, json_type_int);
            na_env->error_count_max = json_object_get_int(param_obj);
            continue;
        case NA_PARAM_SLOW_QUERY_SEC:
            NA_PARAM_TYPE_CHECK(param_obj, json_type_double);
            slow_query_sec = json_object_get_double(param_obj);
            na_env->slow_query_sec.tv_sec = slow_query_sec;
            na_env->slow_query_sec.tv_nsec = 1000000000L * (slow_query_sec - (long)slow_query_sec);
            continue;
        default:
            break;
        }

        // if we didn't find a reconfigurable parameter, try the others
        if (!reconf) {
            switch (i) {
            case NA_PARAM_NAME:
                NA_PARAM_TYPE_CHECK(param_obj, json_type_string);
                strncpy(na_env->name, json_object_get_string(param_obj), NA_NAME_MAX);
                break;
            case NA_PARAM_SOCKPATH:
                NA_PARAM_TYPE_CHECK(param_obj, json_type_string);
                strncpy(na_env->fssockpath, json_object_get_string(param_obj), NA_SOCKPATH_MAX);
                break;
            case NA_PARAM_TARGET_SERVER:
                NA_PARAM_TYPE_CHECK(param_obj, json_type_string);
                strncpy(host_buf, json_object_get_string(param_obj), NA_HOSTNAME_MAX);
                host = na_create_host(host_buf);
                memcpy(&na_env->target_server.host, &host, sizeof(host));
                na_set_sockaddr(&host, &na_env->target_server.addr);
                break;
            case NA_PARAM_BACKUP_SERVER:
                NA_PARAM_TYPE_CHECK(param_obj, json_type_string);
                strncpy(host_buf, json_object_get_string(param_obj), NA_HOSTNAME_MAX);
                host = na_create_host(host_buf);
                memcpy(&na_env->backup_server.host, &host, sizeof(host));
                na_set_sockaddr(&host, &na_env->backup_server.addr);
                na_env->is_use_backup = true;
                break;
            case NA_PARAM_PORT:
                NA_PARAM_TYPE_CHECK(param_obj, json_type_int);
                na_env->fsport = json_object_get_int(param_obj);
                break;
            case NA_PARAM_STPORT:
                NA_PARAM_TYPE_CHECK(param_obj, json_type_int);
                na_env->stport = json_object_get_int(param_obj);
                break;
            case NA_PARAM_STSOCKPATH:
                NA_PARAM_TYPE_CHECK(param_obj, json_type_string);
                strncpy(na_env->stsockpath, json_object_get_string(param_obj), NA_SOCKPATH_MAX);
                break;
            case NA_PARAM_ACCESS_MASK:
                NA_PARAM_TYPE_CHECK(param_obj, json_type_string);
                na_env->access_mask = (mode_t)strtol(json_object_get_string(param_obj), &e, 8);
                break;
            case NA_PARAM_WORKER_MAX:
                NA_PARAM_TYPE_CHECK(param_obj, json_type_int);
                na_env->worker_max = json_object_get_int(param_obj);
                break;
            case NA_PARAM_CONNPOOL_MAX:
                NA_PARAM_TYPE_CHECK(param_obj, json_type_int);
                na_env->connpool_max = json_object_get_int(param_obj);
                break;
            case NA_PARAM_CONNPOOL_USE_MAX:
                NA_PARAM_TYPE_CHECK(param_obj, json_type_int);
                na_env->connpool_use_max = json_object_get_int(param_obj);
                break;
            case NA_PARAM_CLIENT_POOL_MAX:
                NA_PARAM_TYPE_CHECK(param_obj, json_type_int);
                na_env->client_pool_max = json_object_get_int(param_obj);
                break;
            case NA_PARAM_LOOP_MAX:
                NA_PARAM_TYPE_CHECK(param_obj, json_type_int);
                na_env->loop_max = json_object_get_int(param_obj);
                break;
            case NA_PARAM_EVENT_MODEL:
                NA_PARAM_TYPE_CHECK(param_obj, json_type_string);
                na_env->event_model = na_detect_event_model(json_object_get_string(param_obj));
                if (na_env->event_model == NA_EVENT_MODEL_UNKNOWN) {
                    NA_DIE_WITH_ERROR(NA_ERROR_INVALID_JSON_CONFIG);
                }
                break;
            default:
                // no through
                assert(false);
                break;
            }
        }
    }

    na_env->is_extensible_request_buf  = na_env->request_bufsize  < na_env->request_bufsize_max  ? true : false;
    na_env->is_extensible_response_buf = na_env->response_bufsize < na_env->response_bufsize_max ? true : false;

}
void OGRTopoJSONReader::ReadLayers( OGRGeoJSONDataSource* poDS )
{
    if( NULL == poGJObject_ )
    {
        CPLDebug( "TopoJSON",
                  "Missing parset TopoJSON data. Forgot to call Parse()?" );
        return;
    }

    ScalingParams sParams;
    sParams.dfScale0 = 1.0;
    sParams.dfScale1 = 1.0;
    sParams.dfTranslate0 = 0.0;
    sParams.dfTranslate1 = 0.0;
    json_object* poObjTransform = OGRGeoJSONFindMemberByName( poGJObject_, "transform" );
    if( NULL != poObjTransform && json_type_object == json_object_get_type( poObjTransform ) )
    {
        json_object* poObjScale = OGRGeoJSONFindMemberByName( poObjTransform, "scale" );
        if( NULL != poObjScale && json_type_array == json_object_get_type( poObjScale ) &&
            json_object_array_length( poObjScale ) == 2 )
        {
            json_object* poScale0 = json_object_array_get_idx(poObjScale, 0);
            json_object* poScale1 = json_object_array_get_idx(poObjScale, 1);
            if( poScale0 != NULL &&
                (json_object_get_type(poScale0) == json_type_double ||
                 json_object_get_type(poScale0) == json_type_int) &&
                poScale1 != NULL &&
                (json_object_get_type(poScale1) == json_type_double ||
                 json_object_get_type(poScale1) == json_type_int) )
            {
                sParams.dfScale0 = json_object_get_double(poScale0);
                sParams.dfScale1 = json_object_get_double(poScale1);
            }
        }

        json_object* poObjTranslate = OGRGeoJSONFindMemberByName( poObjTransform, "translate" );
        if( NULL != poObjTranslate && json_type_array == json_object_get_type( poObjTranslate ) &&
            json_object_array_length( poObjTranslate ) == 2 )
        {
            json_object* poTranslate0 = json_object_array_get_idx(poObjTranslate, 0);
            json_object* poTranslate1 = json_object_array_get_idx(poObjTranslate, 1);
            if( poTranslate0 != NULL &&
                (json_object_get_type(poTranslate0) == json_type_double ||
                 json_object_get_type(poTranslate0) == json_type_int) &&
                poTranslate1 != NULL &&
                (json_object_get_type(poTranslate1) == json_type_double ||
                 json_object_get_type(poTranslate1) == json_type_int) )
            {
                sParams.dfTranslate0 = json_object_get_double(poTranslate0);
                sParams.dfTranslate1 = json_object_get_double(poTranslate1);
            }
        }
    }

    json_object* poArcs = OGRGeoJSONFindMemberByName( poGJObject_, "arcs" );
    if( poArcs == NULL || json_type_array != json_object_get_type( poArcs ) )
        return;

    OGRGeoJSONLayer* poMainLayer = NULL;

    json_object* poObjects = OGRGeoJSONFindMemberByName( poGJObject_, "objects" );
    if( poObjects == NULL )
        return;

    if( json_type_object == json_object_get_type( poObjects ) )
    {
        json_object_iter it;
        it.key = NULL;
        it.val = NULL;
        it.entry = NULL;
        json_object_object_foreachC( poObjects, it )
        {
            json_object* poObj = it.val;
            ParseObjectMain(it.key, poObj, poDS, &poMainLayer, poArcs, &sParams);
        }
LibraryEntry::LibraryEntry(json_object *j)
{
    json_object *title_json;
    json_object_object_get_ex(j, "title", &title_json);
    title = std::string(json_object_get_string(title_json));

    json_object *synopsis_json;
    json_object_object_get_ex(j, "synopsis", &synopsis_json);
    synopsis = std::string(json_object_get_string(synopsis_json));

    json_object *airing_status_json;
    json_object_object_get_ex(j, "airing_status", &airing_status_json);
    airingStatus = std::string(json_object_get_string(airing_status_json));

    json_object *episode_count_json;
    json_object_object_get_ex(j, "episode_count", &episode_count_json);
    episodeCount = std::string(json_object_to_json_string(episode_count_json));

    json_object *episodes_watched_json;
    json_object_object_get_ex(j, "episodes_watched", &episodes_watched_json);
    episodesWatched = std::string(json_object_to_json_string(episodes_watched_json));

    json_object *library_status_json;
    json_object_object_get_ex(j, "library_status", &library_status_json);
    std::string libraryStatusString = std::string(json_object_get_string(library_status_json));

    if(libraryStatusString.compare("currently-watching") == 0)
        libraryStatus = CURRENTLY_WATCHING;
    else if(libraryStatusString.compare("plan-to-watch") == 0)
        libraryStatus = PLAN_TO_WATCH;
    else if(libraryStatusString.compare("completed") == 0)
        libraryStatus = COMPLETED;
    else if(libraryStatusString.compare("on-hold") == 0)
        libraryStatus = ON_HOLD;
    else if(libraryStatusString.compare("dropped") == 0)
        libraryStatus = DROPPED;
    else /* Undefined, this shouldn't happen (means anime isn't in the user's library) */
        libraryStatus = UNDEFINED;

    json_object *rating_json;
    json_object_object_get_ex(j, "rating", &rating_json);
    rating = std::string(json_object_to_json_string(rating_json));

    json_object *community_rating_json;
    json_object_object_get_ex(j, "community_rating", &community_rating_json);
    communityRating = json_object_get_double(community_rating_json);

    json_object *type_json;
    json_object_object_get_ex(j, "show_type", &type_json);
    type = std::string(json_object_get_string(type_json));

    json_object *genres_json;
    json_object_object_get_ex(j, "genres", &genres_json);
    genres.assign(json_object_array_length(genres_json),"");
    for(int i=0; i<json_object_array_length(genres_json); i++) {
        json_object *genre_json = json_object_array_get_idx(genres_json, i);
        json_object *genre_name_json;
        json_object_object_get_ex(genre_json, "name", &genre_name_json);
        genres[i] = std::string(json_object_get_string(genre_name_json));
    }
}
void OGRCloudantTableLayer::LoadMetadata()
{
    if (bHasLoadedMetadata)
        return;

    bHasLoadedMetadata = TRUE;

    if (pszSpatialDDoc == NULL)
        GetSpatialView();
    if( pszSpatialDDoc == NULL )
        return;

    CPLString osURI("/");
    osURI += osEscapedName;
    osURI += "/";
    osURI += pszSpatialDDoc;

    json_object* poAnswerObj = poDS->GET(osURI);
    if (poAnswerObj == NULL)
        return;

    if ( !json_object_is_type(poAnswerObj, json_type_object) )
    {
        CPLError(CE_Failure, CPLE_AppDefined, "LoadMetadata() failed");
        json_object_put(poAnswerObj);
        return;
    }

    json_object* poRev = json_object_object_get(poAnswerObj, "_rev");
    const char* pszRev = json_object_get_string(poRev);
    if (pszRev)
        osMetadataRev = pszRev;

    json_object* poError = json_object_object_get(poAnswerObj, "error");
    const char* pszError = json_object_get_string(poError);
    if (pszError && strcmp(pszError, "not_found") == 0)
    {
        json_object_put(poAnswerObj);
        return;
    }

    if (poDS->IsError(poAnswerObj, "LoadMetadata() failed"))
    {
        json_object_put(poAnswerObj);
        return;
    }

    json_object* poJsonSRS = json_object_object_get(poAnswerObj, "srsid");
    const char* pszSRS = json_object_get_string(poJsonSRS);
    if (pszSRS != NULL)
    {
        poSRS = new OGRSpatialReference();
        if (poSRS->importFromURN(pszSRS) != OGRERR_NONE)
        {
            delete poSRS;
            poSRS = NULL;
        }
    }

    json_object* poGeomType = json_object_object_get(poAnswerObj, "geomtype");
    const char* pszGeomType = json_object_get_string(poGeomType);

     if (pszGeomType)
    {
        if (EQUAL(pszGeomType, "NONE"))
        {
            eGeomType = wkbNone;
            bExtentValid = TRUE;
        }
        else
        {
            eGeomType = OGRFromOGCGeomType(pszGeomType);

            json_object* poIs25D = json_object_object_get(poAnswerObj, "is_25D");
            if (poIs25D && json_object_get_boolean(poIs25D))
                eGeomType = wkbSetZ(eGeomType);

            json_object* poExtent = json_object_object_get(poAnswerObj, "extent");
            if (poExtent && json_object_get_type(poExtent) == json_type_object)
            {
                json_object* poBbox = json_object_object_get(poExtent, "bbox");
                if (poBbox &&
                    json_object_get_type(poBbox) == json_type_array &&
                    json_object_array_length(poBbox) == 4 &&
                    OGRCloudantIsNumericObject(json_object_array_get_idx(poBbox, 0)) &&
                    OGRCloudantIsNumericObject(json_object_array_get_idx(poBbox, 1)) &&
                    OGRCloudantIsNumericObject(json_object_array_get_idx(poBbox, 2)) &&
                    OGRCloudantIsNumericObject(json_object_array_get_idx(poBbox, 3)))
                {
                    dfMinX = json_object_get_double(json_object_array_get_idx(poBbox, 0));
                    dfMinY = json_object_get_double(json_object_array_get_idx(poBbox, 1));
                    dfMaxX = json_object_get_double(json_object_array_get_idx(poBbox, 2));
                    dfMaxY = json_object_get_double(json_object_array_get_idx(poBbox, 3));
                    bExtentValid = bExtentSet = TRUE;
                }
            }
        }
    }

    json_object* poGeoJSON = json_object_object_get(poAnswerObj, "geojson_documents");
    if (poGeoJSON && json_object_is_type(poGeoJSON, json_type_boolean))
        bGeoJSONDocument = json_object_get_boolean(poGeoJSON);

    json_object* poFields = json_object_object_get(poAnswerObj, "fields");
    if (poFields && json_object_is_type(poFields, json_type_array))
    {
        poFeatureDefn = new OGRFeatureDefn( osName );
        poFeatureDefn->Reference();

        poFeatureDefn->SetGeomType(eGeomType);
        if( poFeatureDefn->GetGeomFieldCount() != 0 ) 
            poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);

        OGRFieldDefn oFieldId("_id", OFTString);
        poFeatureDefn->AddFieldDefn(&oFieldId);

        OGRFieldDefn oFieldRev("_rev", OFTString);
        poFeatureDefn->AddFieldDefn(&oFieldRev);

        int nFields = json_object_array_length(poFields);
        for(int i=0;i<nFields;i++)
        {
            json_object* poField = json_object_array_get_idx(poFields, i);
            if (poField && json_object_is_type(poField, json_type_object))
            {
                json_object* poName = json_object_object_get(poField, "name");
                const char* pszName = json_object_get_string(poName);
                if (pszName)
                {
                    json_object* poType = json_object_object_get(poField, "type");
                    const char* pszType = json_object_get_string(poType);
                    OGRFieldType eType = OFTString;
                    if (pszType)
                    {
                        if (strcmp(pszType, "integer") == 0)
                            eType = OFTInteger;
                        else if (strcmp(pszType, "integerlist") == 0)
                            eType = OFTIntegerList;
                        else if (strcmp(pszType, "real") == 0)
                            eType = OFTReal;
                        else if (strcmp(pszType, "reallist") == 0)
                            eType = OFTRealList;
                        else if (strcmp(pszType, "string") == 0)
                            eType = OFTString;
                        else if (strcmp(pszType, "stringlist") == 0)
                            eType = OFTStringList;
                    }

                    OGRFieldDefn oField(pszName, eType);
                    poFeatureDefn->AddFieldDefn(&oField);
                }
            }
        }
    }

    std::sort(aosIdsToFetch.begin(), aosIdsToFetch.end());

    json_object_put(poAnswerObj);

    return;
}