You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Jsonnet中通过单条件判断批量生成并合并大型对象?

Jsonnet条件生成对象的冗余代码优化

我需要在条件满足时,创建一个大型对象并合并到现有对象中。当前实现可行但存在冗余的if-then-else语句,希望用单个条件判断完成对象生成。

原始可行代码

local something_something = true;
local tst = {
  n1: {
    a: "10.172.52.0/22",
    b: "10.172.56.0/22",
  },
  n2: {
    c: "10.172.60.0/22",
  },
};

{
  aws_route: {
    public: {
      route_table_id: '${aws_route_table.public.id}',
      destination_cidr_block: '0.0.0.0/0',
      gateway_id: '${aws_internet_gateway.tst.id}',
    }
  } + (
    if something_something then {
    ['nat_%s' % zone]: {
      route_table_id: '${aws_route_table.nat_%s.id}' % zone,
      destination_cidr_block: '0.0.0.0/0',
      nat_gateway_id: '${aws_nat_gateway.ngw_%s.id}' % zone,
    }
    for zone in std.objectFields(tst.n1)
  } else {})
  + (
    if something_something then {
    ['nat_%s' % zone]: {
      route_table_id: '${aws_route_table.nat_%s.id}' % zone,
      destination_cidr_block: '0.0.0.0/0',
      nat_gateway_id: '${aws_nat_gateway.ngw_%s.id}' % zone,
    }
    for zone in std.objectFields(tst.n2)
  } else {})
}

预期输出

{
   "aws_route": {
      "nat_a": {
         "destination_cidr_block": "0.0.0.0/0",
         "nat_gateway_id": "${aws_nat_gateway.ngw_a.id}",
         "route_table_id": "${aws_route_table.nat_a.id}"
      },
      "nat_b": {
         "destination_cidr_block": "0.0.0.0/0",
         "nat_gateway_id": "${aws_nat_gateway.ngw_b.id}",
         "route_table_id": "${aws_route_table.nat_b.id}"
      },
      "nat_c": {
         "destination_cidr_block": "0.0.0.0/0",
         "nat_gateway_id": "${aws_nat_gateway.ngw_c.id}",
         "route_table_id": "${aws_route_table.nat_c.id}"
      },
      "public": {
         "destination_cidr_block": "0.0.0.0/0",
         "gateway_id": "${aws_internet_gateway.tst.id}",
         "route_table_id": "${aws_route_table.public.id}"
      }
   }
}

尝试的错误代码及报错

尝试合并两个for推导式,但语法不支持:

{
  aws_route: {
    public: {
      route_table_id: '${aws_route_table.public.id}',
      destination_cidr_block: '0.0.0.0/0',
      gateway_id: '${aws_internet_gateway.tst.id}',
    }
  } + (
    if something_something then {
    ['nat_%s' % zone]: {
      route_table_id: '${aws_route_table.nat_%s.id}' % zone,
      destination_cidr_block: '0.0.0.0/0',
      nat_gateway_id: '${aws_nat_gateway.ngw_%s.id}' % zone,
    }
    for zone in std.objectFields(tst.n1),
    ['nat_%s' % zone]: {
      route_table_id: '${aws_route_table.nat_%s.id}' % zone,
      destination_cidr_block: '0.0.0.0/0',
      nat_gateway_id: '${aws_nat_gateway.ngw_%s.id}' % zone,
    }
    for zone in std.objectFields(tst.n2)
  } else {})
}

报错信息:

STATIC ERROR: tst.jsonnet:26:41: expected for, if or "}" after for clause, got: ","

解决方案

你的思路是合理的,Jsonnet支持通过合并字段数组后推导对象或提取复用逻辑来消除冗余,以下是两种更优实现方式:

方式1:合并字段数组后推导对象

先把tst.n1和tst.n2的字段合并成一个数组,再用单个for推导生成对象,这样只需一次条件判断:

local something_something = true;
local tst = {
  n1: {
    a: "10.172.52.0/22",
    b: "10.172.56.0/22",
  },
  n2: {
    c: "10.172.60.0/22",
  },
};

// 合并两个对象的字段数组
local all_zones = std.objectFields(tst.n1) + std.objectFields(tst.n2);

{
  aws_route: {
    public: {
      route_table_id: '${aws_route_table.public.id}',
      destination_cidr_block: '0.0.0.0/0',
      gateway_id: '${aws_internet_gateway.tst.id}',
    }
  } + (
    if something_something then {
      ['nat_%s' % zone]: {
        route_table_id: '${aws_route_table.nat_%s.id}' % zone,
        destination_cidr_block: '0.0.0.0/0',
        nat_gateway_id: '${aws_nat_gateway.ngw_%s.id}' % zone,
      }
      for zone in all_zones
    } else {}
  )
}

方式2:提取复用的路由对象生成逻辑

如果后续需要扩展更多类似的n3、n4,可以把生成单个nat路由的逻辑提取成局部函数,再批量生成后合并:

local something_something = true;
local tst = {
  n1: {
    a: "10.172.52.0/22",
    b: "10.172.56.0/22",
  },
  n2: {
    c: "10.172.60.0/22",
  },
};

// 提取生成单个nat路由的函数
local make_nat_route(zone) = {
  ['nat_%s' % zone]: {
    route_table_id: '${aws_route_table.nat_%s.id}' % zone,
    destination_cidr_block: '0.0.0.0/0',
    nat_gateway_id: '${aws_nat_gateway.ngw_%s.id}' % zone,
  }
};

// 批量生成并合并所有nat路由对象
local all_nat_routes = std.foldl(
  (acc, zone) => acc + make_nat_route(zone),
  std.objectFields(tst.n1) + std.objectFields(tst.n2),
  {}
);

{
  aws_route: {
    public: {
      route_table_id: '${aws_route_table.public.id}',
      destination_cidr_block: '0.0.0.0/0',
      gateway_id: '${aws_internet_gateway.tst.id}',
    }
  } + (if something_something then all_nat_routes else {})
}

这两种方式都能实现单个条件判断生成所有需要的对象,同时消除代码冗余,第二种方式的扩展性更强,适合后续新增更多区域的场景。


内容的提问来源于stack exchange,提问作者NarūnasK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 18:15:37