Site icon Blah Bethany

Storing flattened JSON (key-value pairs) with variable value types

I have JSON documents with no defined schema. Each document may have different schema and values.

{
    "location":
    {
        "latitude": 58.23,
        "longitude": 25.11
    },
    "building": "A1",
    "active": true,
    "parameters": [ 1, { "scanInterval": 1000 } ]
}

These JSON documents are flattened – formatted into Key-Value pairs.

{
    "location.latitude": 58.23,
    "location.longitude": 25.11,
    "building": "A1",
    "active": true,
    "parameter[0]": 1,
    "parameter[1].scanInterval": 1000
}

Key is always String.

Value can be StringNumberBoolean.

These key-value pairs will be stored in SQL table. The requirement is to be able to filter key-values based on their JSON native values.

SELECT .... FROM ... WHERE [Key] = @key AND [Value] > @value; -- [Value] is integer/float
SELECT .... FROM ... WHERE [Key] = @key AND [Value] != @value; -- [Value] is bit/boolean
SELECT .... FROM ... WHERE [Key] = @key AND [Value] = @value; -- [Value] is string

Which makes me question – how do I design my table?

OPTION A) Casting.

CREATE TABLE [dbo].[OptionA](
    ....
    [Key] [nvarchar](max),
    [ValueType] [nvarchar](max)
    [Value] [nvarchar](max)
)

Always store [Value] as String, when querying data, select rows with matching [ValueType] and cast value:

... WHERE [ValueType] = 'Number' AND [Key] = @key AND CAST([Value] AS FLOAT) > @value

OPTION B) Column for each value type.

CREATE TABLE [dbo].[OptionB](
    ....
    [Key] [nvarchar](50),
    [StringValue] [nvarchar](50) NULL,
    [NumericValue] [float] NULL,
    [BooleanValue] [bit] NULL
)

There are 3 columns. Each column for 1 value type. Out of all 3 columns only 1 can contain value and the rest are NULL.

When querying data, select the column with the appropriate value type:

SELECT .... FROM ... WHERE [Key] = @key AND [NumericValue] > @value

Which option yields the best results or is/seems overall better? Perhaps there are some other better alternatives?

I’m leaning more towards the A) approach, however all the casting may be adding extra complexity and may have potential performance hits.

Exit mobile version