jsony icon indicating copy to clipboard operation
jsony copied to clipboard

How to omit items that have default values?

Open iffy opened this issue 1 year ago • 2 comments

I have a situation where JSON strings omit default values. For instance in the code below, if interval is omitted or less than 0, it should be set to 100. What can I do with dumpHook/skipHook to omit default values when I serialize my objects?

import jsony, std/json, std/unittest

type
  Thing = object
    name*: string
    interval*: int

proc newHook*(x: var Thing) =
  if x.interval == 0:
    x.interval = 100

test "defaultvalue":
  let original = """{"name":"bob"}"""
  let thing = original.fromJson(Thing)
  check thing.interval == 100
  let serialized = thing.toJson()
  check parseJson(serialized) == parseJson(original)

test "specificvalue":
  let original = """{"name":"bob", "interval": 200}"""
  let thing = original.fromJson(Thing)
  check thing.interval == 200
  let serialized = thing.toJson()
  check parseJson(serialized) == parseJson(original)

The output of the above is:

parseJson(serialized) was {"name":"bob","interval":100}
parseJson(original) was {"name":"bob"}
[FAILED] defaultvalue
[OK] specificvalue

iffy avatar Jan 02 '24 15:01 iffy

I think #85 if merged could provide a solution :)

pietroppeter avatar Apr 01 '24 15:04 pietroppeter

import std/json, pkg/jsony

type
  Thing = object
    name*: string
    interval*: int
  
  AnotherThing = object
    name*: string
    interval*: int

proc newHook(x: var Thing) =
  if x.interval == 0:
    x.interval = 100

proc skipHook(T: typedesc[Thing], v: int, key: string): bool =
  if key == "interval":
    result = v == 100

block:
  let
    original = """{"name":"bob"}"""
    thing = jsony.fromJson(original, Thing)
    serialized = jsony.toJson(thing)
  
  assert thing.interval == 100
  assert serialized == original
  assert jsony.fromJson(serialized) == jsony.fromJson(original)
  assert json.parseJson(serialized) == json.parseJson(original)

block:
  let
    original = """{"name":"bob", "interval": 200}"""
    thing = original.fromJson(Thing)
    serialized = jsony.toJson(thing)

  assert thing.interval == 200
  assert serialized != original
  assert jsony.fromJson(serialized) == jsony.fromJson(original)
  assert json.parseJson(serialized) == json.parseJson(original)

block:
  let
    original = """{"name": "bob"}"""
    athing = jsony.fromJson(original, AnotherThing)
    serialized = jsony.toJson(athing)
  assert serialized == """{"name":"bob","interval":0}""" # not covered by skipHook
  assert jsony.fromJson(serialized) != jsony.fromJson(original)
  assert json.parseJson(serialized) != json.parseJson(original)

georgelemon avatar Apr 02 '24 06:04 georgelemon