CREATE OR REPLACE FUNCTION jsonb_diff(a_ jsonb, b_ jsonb) RETURNS jsonb AS $$ SELECT jsonb_object_agg("keys"."key", "a"."value") FROM ( SELECT jsonb_object_keys(a_) AS "key" UNION SELECT jsonb_object_keys(b_) AS "key" ) AS "keys" LEFT JOIN (SELECT "key", "value" FROM jsonb_each(a_)) AS "a" ON "a"."key" = "keys"."key" LEFT JOIN (SELECT "key", "value" FROM jsonb_each(b_)) AS "b" ON "b"."key" = "keys"."key" WHERE "a"."value" != "b"."value" OR "a"."key" || "b"."key" IS NULL; $$ LANGUAGE sql IMMUTABLE; SELECT jsonb_diff( to_jsonb('{ "a": 1, "b": 2, "c": 3, "d": 4 }'::json), to_jsonb('{ "a": 1, "b": 5, "c": 3, "x": 7 }'::json) ); jsonb_diff ----------------------------- {"b": 2, "d": 4, "x": null}