google / jsonnet

Jsonnet - The data templating language
http://jsonnet.org
Apache License 2.0
6.98k stars 440 forks source link

std.mergePatch loses hidden fields #2 #1041

Open dxlr8r opened 1 year ago

dxlr8r commented 1 year ago

Sorry for resurrecting an old thread. But I came a cross the same issue the other day. I use Jsonnet for Terraform, and the way I create modules using Jsonnet, and want to pass data between the modules (which are merged using std.mergePatch), hidden fields I want to lookup are missing after I merge them.

sparkprime commented 1 year ago

Can't you make them non-hidden? Merge Patch doesn't have a concept of hidden fields because it's a JSON standard.

dxlr8r commented 1 year ago

Terraform is very particular with what fields it accept; so the short answer no. The longer answer is, yes of course there are workarounds. I have one implemented, but the code is far more readable, maintainable less DRY without it. Now I have to add several lines of boilerplate per module.

sparkprime commented 1 year ago

Can you use the language's mixin support instead of std.mergePatch?

dxlr8r commented 1 year ago

That would be very difficult. In this case, I want to merge several sources. Some of those sources are jsonnet, and there mixin can be used. Others are HCL converted to JSON, one could perhaps write some code to edit the JSON and add + where needed, but that seems like a dirty hack.

sparkprime commented 1 year ago

you could write a wrapper that imports the json and uses it to build an object that will mix together nicely

dxlr8r commented 1 year ago

I could, many different workarounds one could think of. Personally I believe people would except std.mergePatch to merge Jsonnet objects. My alternatives for my use case is to either create a recursive function that merges Jsonnet objects, which would work like std.mergePatch but without deleting hidden fields, or wait for std.mergePatch to be updated.

serge-salamanka commented 8 months ago

i have come up to the function like this to solve import from json to make it a jsonnet object

local main       = import 'lib/main.libsonnet';
local overrides  = std.parseJson(importstr 'etc/config.json'); // for safe import

// reference to the helpful comment because of the missing documentation https://stackoverflow.com/a/76149084
local jsonnet_object(o) = {
    [c.key]+: if std.isObject(c.value) then jsonnet_object(c.value) else c.value
    for c in std.objectKeysValues(o)
    if std.isObject(c.value)
} + {
  [c.key]: c.value
  for c in std.objectKeysValues(o)
  if !std.isObject(c.value)
};

local config     =  main {config+: jsonnet_object(overrides.config)};