openwrt / openwrt/libubox

JSON -> Blob conversion makes number parsing hard, particularly for doubles

Open
#8 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C
Stars
32
Forks
35
PR merge metrics
No merged PRs in 30d

Description

The root issue is that Blobs' have a lot of numeric types and JSON only has one. The JSON-C library attempts to guess the type and this guess is reflected in the blob format:

    case json_type_int: {
        int64_t i64 = json_object_get_int64(obj);
        if (i64 >= INT32_MIN && i64 <= INT32_MAX) {
            blobmsg_add_u32(b, name, (uint32_t)i64);
        } else {
            blobmsg_add_u64(b, name, (uint64_t)i64);
        }
        break;
    }
    case json_type_double:
        blobmsg_add_double(b, name, json_object_get_double(obj));
        break;

However, consider the case of passing a double in via JSON. The upstream code might pass something like 2.1, or it might pass something like 2, noting that JSON/Javascript thinks of all things as Numbers; the former will be turned into a BLOBMSG_TYPE_DOUBLE while the latter will be turned into a BLOBMSG_TYPE_INT32. As far as I understand it, the only way to handle this with a policy when parsing the resulting message is to use BLOBMSG_TYPE_UNSPEC and then write your own conversion. e.g.

static inline double blobmsg_cast_double(struct blob_attr *attr)
{
    double tmp = 0;

    if (blobmsg_type(attr) == BLOBMSG_TYPE_INT64)
        tmp = blobmsg_get_u64(attr);
    else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT32)
        tmp = (int32_t)blobmsg_get_u32(attr);
    else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT16)
        tmp = (int16_t)blobmsg_get_u16(attr);
    else if (blobmsg_type(attr) == BLOBMSG_TYPE_INT8)
        tmp = (int8_t)blobmsg_get_u8(attr);
    else if (blobmsg_type(attr) == BLOBMSG_TYPE_DOUBLE)
        tmp = blobmsg_get_double(attr);

    return tmp;
}

This whole situation makes me a little uncomfortable. My preference would be for all JSON numbers to be represented as doubles in the blobmsg, but this is hardly backwards compatible. A conservative approach would be to add a BLOBMSG_CAST_DOUBLE type (cf BLOBMSG_CAST_INT64) and the helper functions above. I'd also like there to be equivalent double->int casting functions, potentially changing the behaviour of BLOBMSG_CAST_INT64 to support doubles.

Thoughts?

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the JSON-to-blob conversion and the existing BLOBMSG_CAST_INT64 policy and helper APIs. Review the compatibility implications described in the issue, then establish the agreed numeric casting behavior and add coverage for integer and double inputs once the design is settled.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.