diff --git a/README.md b/README.md index 4b9f248..363d116 100644 --- a/README.md +++ b/README.md @@ -277,6 +277,42 @@ Gives us: "{"a":1,"b":0.5}" ``` +Also, `skipHook` can be used at runtime to skip fields based on their current value. For example: +```nim +type + Boo = ref object + hoo: string + x: seq[string] + y: seq[int] + i: int + b: bool + + Woo = object + boo: Boo + +proc skipHook(v: Boo, key: string): bool = + ## Skip `nil` fields + result = v == nil + +proc skipHook(v: string, key: string): bool = + ## skip all fields that contains empty strings + result = v.len == 0 + +proc skipHook[T](v: seq[T], key: string): bool = + # skip all fields that contains empty sequences + result = v.len == 0 + +let w = Woo(boo: Boo()) +assert w.toJson() == """{"boo":{"i":0,"b":false}}""" + +let w2 = Woo() +assert w2.toJson() == "{}" + +let b = Boo() +assert b.toJson() == + """{"i":0,"b":false}""" +``` + ## Static writing with `toStaticJson`. Sometimes you have some json, and you want to write it in a static way. There is a special function for that: diff --git a/src/jsony.nim b/src/jsony.nim index 0fcb67b..e6db6b9 100644 --- a/src/jsony.nim +++ b/src/jsony.nim @@ -827,6 +827,24 @@ proc dumpHook*(s: var string, v: object) = s.dumpKey(k) s.dumpHook(e) inc i + elif compiles(skipHook(type(v), e, k)): + if skipHook(type(v), e, k): + discard + else: + if i > 0: + s.add ',' + s.dumpKey(k) + s.dumpHook(e) + inc i + elif compiles(skipHook(e, k)): + if skipHook(e, k): + discard + else: + if i > 0: + s.add ',' + s.dumpKey(k) + s.dumpHook(e) + inc i else: if i > 0: s.add ',' diff --git a/tests/test_skipHook.nim b/tests/test_skipHook.nim index f1b51a0..e0741b5 100644 --- a/tests/test_skipHook.nim +++ b/tests/test_skipHook.nim @@ -1,5 +1,4 @@ import jsony - type Conn = object id: int @@ -15,3 +14,45 @@ proc skipHook(T: typedesc[Foo], key: static string): bool = let v = Foo(a:1, password: "12345", b:0.6, conn: Conn(id: 1)) doAssert v.toJson() == """{"a":1,"b":0.6}""" + +type + Boo = ref object + hoo: string + x: seq[string] + y: seq[int] + i: int + b: bool + + Woo = object + boo: Boo + + Moo = object + boo: Boo + +proc skipHook(T: typedesc[Woo], v: Boo, key: string): bool = + result = v == nil + +proc skipHook(v: string, key: string): bool = + result = v.len == 0 + +proc skipHook[T](v: seq[T], key: string): bool = + result = v.len == 0 + +let w = Woo(boo: Boo()) +doAssert w.toJson() == + """{"boo":{"i":0,"b":false}}""" +let w2 = Woo() +doAssert w2.toJson() == + """{}""" +let b = Boo() +doAssert b.toJson() == + """{"i":0,"b":false}""" + +block: + let m = Moo() # not covered by `skipHook` + doAssert m.toJson() == + """{"boo":null}""" +block: + let m = Moo(boo: Boo(hoo: "just moo")) + doAssert m.toJson() == + """{"boo":{"hoo":"just moo","i":0,"b":false}}""" \ No newline at end of file