Skip to main content

Reject Duplicate JSON Keys Before Queuing a Job

Updated 5 min readMarkdown
Reject Duplicate JSON Keys Before Queuing a Job

A hypothetical publishing job arrives with this configuration:

{"account":"studio-main","caption":"Version A","caption":"Version B"}

There is one account and a decision that has been written twice. Which caption should the reviewer approve?

Python's standard JSON decoder does not ask. By default, it accepts repeated member names and keeps the last value. Once the input has become a dictionary, the earlier caption is gone. A validator that receives only that dictionary cannot tell that the source contained two competing instructions.

Reject that ambiguity while the decoder still has the original name-value pairs.

Parsing can erase evidence

With the default decoder, this expression:

json.loads('{"caption":"Version A","caption":"Version B"}')

produces:

{"caption": "Version B"}

That is documented Python behavior, not a guess about which value a publishing service will use. Another parser or viewer may handle repeated names differently. A workflow that relies on everyone making the same choice has left an avoidable decision inside its input format.

The Python JSON documentation explains this behavior and identifies object_pairs_hook as the extension point. The hook receives an object's decoded name-value pairs before they are collapsed into the ordinary dictionary result.

Reject repetition as each object is built

This small helper accepts a JSON text whose top-level value must be an object:

import json


def unique_object(pairs):
    result = {}
    for name, value in pairs:
        if name in result:
            raise ValueError("Repeated JSON object member")
        result[name] = value
    return result


def parse_job_object(text):
    result = json.loads(text, object_pairs_hook=unique_object)
    if not isinstance(result, dict):
        raise ValueError("Expected a JSON object")
    return result

The hook rejects a repeated name even when the two values happen to match. That keeps the rule simple: each name appears once within a particular object. It does not depend on deciding whether two values are equivalent.

The generic error deliberately omits the field value and the entire source document. An application can report that the input needs correction without copying captions, account information or other job data into a general-purpose log. More detailed feedback needs an intentional policy about where that information is shown.

The top-level check is a separate contract. JSON can represent arrays, strings, numbers, booleans and null; this example expects a configuration object. Valid JSON syntax alone does not establish that a value has the shape a job needs.

Check the boundary cases

The hook runs for nested objects too. Repeating zone inside schedule, or file inside an object in a media array, therefore raises an error. Checking only the top-level names would miss both cases.

Names are compared after JSON string escapes have been decoded. These two spellings name the same field:

{"caption":"Version A","\u0063aption":"Version B"}

The helper rejects that input. Searching the raw text for an exact repeated spelling would not reliably catch it.

The rule is local to each object. A caption in a draft object and a caption in a separate published object are allowed. A global set of every name seen anywhere in the document would incorrectly reject that structure.

Case and Unicode normalization are different decisions. This helper treats caption and Caption as distinct names. It also leaves canonically equivalent Unicode spellings distinct when their decoded strings differ. If an application later transforms names, it must consider collisions introduced at that later boundary. The parser does not choose that naming policy.

Validate the resulting job separately

Successful parsing establishes a narrow property: the decoded input did not repeat an object member name under this comparison rule, and its top-level value is an object.

It does not establish that an account exists, a media file is accessible, a schedule is sensible or a field is permitted. Validate required fields, unknown fields, types and allowed values after parsing. Check the actual job's permissions before it can execute.

Resource limits also belong to the surrounding service. This example does not impose an input byte budget, nesting limit or numeric range. Python's decoder has other documented behaviors, including accepting NaN and infinity tokens by default. Use an explicit policy for those if the receiving contract forbids them. This helper is not a complete strict-JSON or secure-upload implementation.

What the local checks established

Eight local test methods covered a valid nested configuration; repeated top-level names with equal and unequal values; a duplicate in a nested object; a duplicate inside an array element; an escaped name collision; the same name in separate objects; distinct case and Unicode spellings; and invalid root shapes or malformed syntax.

The default-decoder example was executed too: its resulting caption was Version B. These checks verify the illustrated behavior against those fixtures. They do not certify a different parser, a production service or a downstream worker.

Put the check before the queue

Parse the original input with the repetition check, validate the resulting object, and build the reviewable job from that validated representation. Preserve the approved representation through the handoff to execution. If a later step reparses a different source or applies new naming rules, review that boundary as well.

This article is published by the official SMTasker account. Its feature overview describes preparing photos, videos and captions, choosing publishing windows, and reviewing work executed through connected Android devices with a Windows or Mac client. The Python helper here illustrates a design pattern; it does not describe SMTasker's internal parser or claim a native duplicate-key check.

A publishing job should reach its reviewer with one explicit value for each field. Catch repeated names before parsing makes the conflicting instruction disappear.

About the author

  • Official SMTasker account. We publish engineering notes on Android social workflows: reproducible setup, content preparation, scheduling and checking execution. SMTasker brings supported social automation, connected Android devices and activity logs into a browser dashboard, with a Windows or Mac client. Skye AI Manager helps prepare settings for review; MCP connects compatible external assistants with the permissions you choose. Here we share practical examples and explain their limits. Sample code illustrates design patterns and is not a claim about SMTasker internals. Explore the product: https://smtasker.com/

No comments yet. Be the first to comment.