serde-rs / json

Strongly typed JSON library for Rust
Apache License 2.0
4.88k stars 556 forks source link

Add mechanism to allow non-pretty-printing of some fields while pretty-printing parent object #611

Closed danielthegray closed 4 years ago

danielthegray commented 4 years ago

There are some cases where I believe it would be useful to pretty-print an entire object, but forego the pretty-printing for a field of that object where it is more desirable for the JSON object under that field to be in one line.

Case in point, the JSON files encoded for my Vaultfile project. The basic idea is a file where people can store shared secrets using public-key cryptography.

Since vaultfiles would be meant to be added to source control, it would be useful for them to have secret values and the different public keys on separate lines. However, pretty printing the RSA public key as well makes it a bit more of a pain since it adds ~70 new lines to the file (instead of just one, as I would prefer).

Example:

{                                                                                                                                                                                                                                             
  "keys": {
    "daniel": {
      "n": [
        142549767,
        3518821673,
        621066004,
        4102229598,
        3153653357,
        2032560477,
        2589951819,
        1867303806,
        1318670661,
        997240273,
        2425225238,
        3450276547,
        1270029200,
        3043994472,
        3888620354,
        3764135483,
        3350298362,
        2226845209,
        1251720617,
        3138297150,
        475545373,
        2992032404,
        1157448551,
        3568826980,
        3247063395,
        508676771,
        3063833647,
        1941287772,
        4086787650,
        3654192563,
        2907691465,
        2740011775,
        4114212565,
        2377598490,
        4030765140,
        183734624,
        3154235505,
        2339535548,
        695197640,
        3640636449,
        2952022944,
        235284495,
        2837702651,
        2224583432,
        2976947853,
        3323400546,
        160814843,
        2196341190,
        3743805216,
        1176620751,
        3530369584,
        2564729300,
        2915362645,
        2320657427,
        3238025292,
        3775762401,
        1436812344,
        1352758797,
        1445046480,
        3924148788,
        1940390180,
        2403721693,
        723029722,
        2628567866
      ],
      "e": [
        65537
      ]
    }
  },
  "secrets": {}
}

instead of the terser:

{
  "keys": {
    "daniel": { "n": [ 142549767, 3518821673, 621066004, 4102229598, 3153653357, 2032560477, 2589951819, 1867303806, 1318670661, 997240273, 2425225238, 3450276547, 1270029200, 3043994472, 3888620354, 3764135483, 3350298362, 2226845209, 1251720617, 3138297150, 475545373, 2992032404, 1157448551, 3568826980, 3247063395, 508676771, 3063833647, 1941287772, 4086787650, 3654192563, 2907691465, 2740011775, 4114212565, 2377598490, 4030765140, 183734624, 3154235505, 2339535548, 695197640, 3640636449, 2952022944, 235284495, 2837702651, 2224583432, 2976947853, 3323400546, 160814843, 2196341190, 3743805216, 1176620751, 3530369584, 2564729300, 2915362645, 2320657427, 3238025292, 3775762401, 1436812344, 1352758797, 1445046480, 3924148788, 1940390180, 2403721693, 723029722, 2628567866 ], "e": [ 65537 ] }                                                                                                     
  },
  "secrets": {}
}
dtolnay commented 4 years ago

I would prefer not to build this into serde_json, but the Formatter that is used for layout by the serializer is plugable (https://docs.rs/serde_json/1.0.56/serde_json/struct.Serializer.html#method.with_formatter) and you could write one which generates the layout that you showed, either via a heuristic that applies to numeric arrays or maps with one entry, or based on key path such that the caller would indicate they want keys.daniel placed on one line.