static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
{
    cJSON *op = 0;
    cJSON *path = 0;
    cJSON *value = 0;
    cJSON *parent = 0;
    int opcode = 0;
    char *parentptr = 0;
    char *childptr = 0;

    op = cJSON_GetObjectItem(patch, "op");
    path = cJSON_GetObjectItem(patch, "path");
    if (!op || !path)
    {
        /* malformed patch. */
        return 2;
    }

    /* decode operation */
    if (!strcmp(op->valuestring, "add"))
    {
        opcode = 0;
    }
    else if (!strcmp(op->valuestring, "remove"))
    {
        opcode = 1;
    }
    else if (!strcmp(op->valuestring, "replace"))
    {
        opcode = 2;
    }
    else if (!strcmp(op->valuestring, "move"))
    {
        opcode = 3;
    }
    else if (!strcmp(op->valuestring, "copy"))
    {
        opcode = 4;
    }
    else if (!strcmp(op->valuestring, "test"))
    {
        /* compare value: {...} with the given path */
        return cJSONUtils_Compare(cJSONUtils_GetPointer(object, path->valuestring), cJSON_GetObjectItem(patch, "value"));
    }
    else
    {
        /* unknown opcode. */
        return 3;
    }

    /* Remove/Replace */
    if ((opcode == 1) || (opcode == 2))
    {
        /* Get rid of old. */
        cJSON_Delete(cJSONUtils_PatchDetach(object, path->valuestring));
        if (opcode == 1)
        {
            /* For Remove, this is job done. */
            return 0;
        }
    }

    /* Copy/Move uses "from". */
    if ((opcode == 3) || (opcode == 4))
    {
        cJSON *from = cJSON_GetObjectItem(patch, "from");
        if (!from)
        {
            /* missing "from" for copy/move. */
            return 4;
        }

        if (opcode == 3)
        {
            /* move */
            value = cJSONUtils_PatchDetach(object, from->valuestring);
        }
        if (opcode == 4)
        {
            /* copy */
            value = cJSONUtils_GetPointer(object, from->valuestring);
        }
        if (!value)
        {
            /* missing "from" for copy/move. */
            return 5;
        }
        if (opcode == 4)
        {
            value = cJSON_Duplicate(value, 1);
        }
        if (!value)
        {
            /* out of memory for copy/move. */
            return 6;
        }
    }
    else /* Add/Replace uses "value". */
    {
        value = cJSON_GetObjectItem(patch, "value");
        if (!value)
        {
            /* missing "value" for add/replace. */
            return 7;
        }
        value = cJSON_Duplicate(value, 1);
        if (!value)
        {
            /* out of memory for add/replace. */
            return 8;
        }
    }

    /* Now, just add "value" to "path". */

    /* split pointer in parent and child */
    parentptr = cJSONUtils_strdup(path->valuestring);
    childptr = strrchr(parentptr, '/');
    if (childptr)
    {
        *childptr++ = '\0';
    }
    parent = cJSONUtils_GetPointer(object, parentptr);
    cJSONUtils_InplaceDecodePointerString(childptr);

    /* add, remove, replace, move, copy, test. */
    if (!parent)
    {
        /* Couldn't find object to add to. */
        free(parentptr);
        cJSON_Delete(value);
        return 9;
    }
    else if (parent->type == cJSON_Array)
    {
        if (!strcmp(childptr, "-"))
        {
            cJSON_AddItemToArray(parent, value);
        }
        else
        {
            cJSON_InsertItemInArray(parent, atoi(childptr), value);
        }
    }
    else if (parent->type == cJSON_Object)
    {
        cJSON_DeleteItemFromObject(parent, childptr);
        cJSON_AddItemToObject(parent, childptr, value);
    }
    else
    {
        cJSON_Delete(value);
    }
    free(parentptr);

    return 0;
}
Beispiel #2
0
static int set_value(cJSON *root, const char *json_pointer, cJSON *value)
{
	if (root == NULL) {
		return -1;
	}
	const int len = strlen(json_pointer);
	int offset = 0;
	if (offset == len) {
		//如果为""
		return -1;
	}
	cJSON *parent = root;
	char *key = NULL;
	while (1) {
		free(key);
		key = get_key(json_pointer, &offset);
		if (key == NULL) {
			return -1;
		}
		if (offset >= len) {
			//表示没有下一个key了
			break;
		}

		cJSON *child = NULL;
		if (parent->type == cJSON_Object) {
			child = cJSON_GetObjectItem(parent, key);
			if (child == NULL) {
				//总是创建object而不是数组
				child = cJSON_CreateObject();
				cJSON_AddItemToObject(parent, key, child);
			} else if (child->type != cJSON_Object && child->type != cJSON_Array) {
				child = cJSON_CreateObject();
				cJSON_ReplaceItemInObject(parent, key, child);
			} else {
				//do nothing
			}
		} else if (parent->type == cJSON_Array) {
			int index = atoi(key);
			child = cJSON_GetArrayItem(parent, index);
			if (child == NULL) {
				//总是创建object而不是数组
				child = cJSON_CreateObject();
				cJSON_InsertItemInArray(parent, index, child);
			} else if (child->type != cJSON_Object && child->type != cJSON_Array) {
				child = cJSON_CreateObject();
				cJSON_ReplaceItemInArray(parent, index, child);
			} else {
				//do nothing
			}
		} else {
			//不应该执行到这里
			printf("===>not impossible\n");

		}

		parent = child;

	}

	if (parent->type == cJSON_Array) {
		//key必须为0 or 123,456, '-'表示添加到最后面
		if (strcmp("-", key) == 0) {
			cJSON_AddItemToArray(parent, value);
		} else {
			int index = atoi(key);
			//strtol()
			cJSON_InsertItemInArray(parent, index, value);
		}

	} else if (parent->type == cJSON_Object) {
		//cJSON_AddItemToObject(parent,key,value);
		cJSON *oldValue = cJSON_GetObjectItem(parent, key);
		if (oldValue == NULL) {
			cJSON_AddItemToObject(parent, key, value);

		} else {
			cJSON_ReplaceItemInObject(parent, key, value);

		}

		//cJSON *kk = cJSON_GetObjectItem(parent, key);

	} else {
		//null,number,string,boolean
		//不能够添加
		printf("=====>noooo\n");
	}
	free(key);
	return 0;

}