编程语言模板引擎CLI【免费下载链接】jsonnetJsonnet - The data templating language项目地址https://gitcode.com/gh_mirrors/js/jsonnet点击查看免费下载导读Jsonnet 是一种数据模板语言其对象模型自带继承、字段覆写与延迟求值等面向对象语义常被用来生成 Kubernetes 等系统的复杂配置。java_comparison目录以一份微博同步管道twitter-to-redis的 ReplicationController 配置为例演示了如何把一份使用了面向对象特性的 Jsonnet 程序以保持 JSON 输出结构完全一致的方式翻译成同样使用面向对象特性的 Java 程序。读完本文你将掌握 Jsonnet 对象/字段/隐藏字段/继承在 Java 侧的等价映射规则、两套代码的编译运行方式以及为什么这种翻译只能覆盖两个语言能力集合的交集部分。一、示例背景与目录结构java_comparison子目录位于仓库根目录 java_comparison/ 下包含 8 个文件构成一套完整的对照实验文件作用base-template.libsonnetJsonnet 侧的基础模板相当于 Java 侧BaseTemplatesub-template.jsonnetJsonnet 侧的子模板通过继承并覆写字段sub-template.json参考输出 JSON两份实现都应产出完全相同的这份结果BaseTemplate.javaJava 侧的基础模板类SubTemplate.javaJava 侧的子模板类继承覆写JsonnetObject.java所有 Jsonnet 对象在 Java 侧的公共基类JsonnetValue.javaJava 侧的价值物化manifestation访问器Test.javaJava 入口选择对象并输出到 stdout其中 Java 侧的所有类都对应 Jsonnet 侧定义的对象BaseTemplate↔ 基础模板、BaseTemplateSpec↔spec对象、BaseTemplateSpecSpec↔spec.spec、Container0↔containers[0]、Env0↔env[0]而SubTemplate则对应sub-template.jsonnet中通过对象拼接产生的覆写结果。二、为什么可以用 Java 翻译 Jsonnet能力交集的说明原文档明确指出了这次翻译成立的前提——两个语言只在能力交集内可以互相翻译不能从 Jsonnet 翻译到 Java 的部分Jsonnet 具有 mixin对象拼接/组合和虚内部类virtual inner classes等特性Java 没有直接对应的语言构造。例如仓库教程中展示的把若干 mixin 对象用叠加出一个新模板的写法参见 examples/mixins.jsonnet 与 doc/learning/tutorial.html 中的 mixins 小节就无法用 Java 的继承体系逐字还原。不能从 Java 翻译到 Jsonnet 的部分Java 具有可变状态mutable state和 I/O 能力而 Jsonnet 是纯函数式、无副作用的求值语言天然表达不了这类行为。执行顺序不同Jsonnet 是惰性求值lazy字段只在被引用时才计算Java 是急切求值eager构造对象时字段方法已经就绪。因此翻译时要求示例程序不能依赖求值顺序。本次示例恰好完全落在两者的交集内只用了继承、覆写、隐藏字段、参数化默认值这些 Jsonnet 与 Java 都能表达的特性因此可以做到**结构保持structure-preserving**的翻译即两边生成的 JSON 完全一致。三、运行方式对照3.1 运行 Jsonnet 版本在java_comparison目录下执行jsonnet sub-template.jsonnet输出即为 sub-template.json 中的内容。该命令要求本仓库的 Jsonnet 解释器已经构建完成项目构建方式参见仓库根目录的 Makefile 与 CMakeLists.txt也可直接make或按 README.md 指引构建。3.2 运行 Java 版本javac *.java java Test | jsonnet -这里有两个关键点javac *.java会一次性编译目录内的全部 5 个 Java 文件JsonnetObject.java、JsonnetValue.java、BaseTemplate.java、SubTemplate.java、Test.java因为SubTemplate依赖BaseTemplateTest又依赖它们与框架类整目录编译可自动解决这些依赖。| jsonnet -表示把 Java 程序的输出管道给jsonnet命令并以-作为输入文件名由 Jsonnet 解释器对单行 JSON 做格式化pretty-print弥补 Java 侧单行输出的简化处理使最终效果与 Jsonnet 直接输出一致。四、翻译规则从 Jsonnet 对象模型到 Java 类原文档给出了一套非常清晰的逐条映射规则可归纳为下面这张对照表Jsonnet 概念Java 等价实现动态类型一切值无静态类型所有值一律声明为Object隐式的 public 可见性所有方法、类一律public数组[...]Object[]原始值Boolean/Double/String数字统一用Double对象object命名类的单例实例且该类继承JsonnetObject对象字段field无参方法0 参数方法字段在 Jsonnet 中是虚的可被覆写因此 Java 方法天然是 virtual 的隐藏字段::不直接作为可物化字段通过nonHiddenFields()返回的字段名集合区分不在集合中的字段视为隐藏字段对象继承/覆写、field:Java 类继承 方法覆写4.1 字段到方法的转换看 Jsonnet 基础模板 base-template.libsonnet{ // Mandatory param accessToken:: error accessToken must be defined, // Optional params image:: gcr.io/cooltool-1009/pipeline_image:latest, extraEnv:: [], apiVersion: v1, kind: ReplicationController, ... }对应 Java 侧 BaseTemplate.java// Mandatory param public Object accessToken() { throw new RuntimeException(accessToken must be defined); } // Optional params public Object image() { return gcr.io/cooltool-1009/pipeline_image:latest; } public Object[] extraEnv() { return new Object[]{}; } public Object apiVersion() { return v1; } public Object kind() { return ReplicationController; }注意两点必选参数的强制语义Jsonnet 用accessToken:: error accessToken must be defined声明这是一个必须由子类提供的参数——若未覆写就物化该字段会触发error。Java 侧对应地让方法直接throw new RuntimeException(accessToken must be defined)把缺失必填参数从运行时错误语义上对齐。隐藏字段的默认值image、extraEnv使用::声明为隐藏字段意思是这是我的参数不该直接出现在最终 JSON 里只允许被内部引用。在 Java 侧它们只是普通方法靠nonHiddenFields()不收录其名字来保证不会出现在输出中。4.2 隐藏字段的显式建模nonHiddenFields()Jsonnet 中字段有两种状态可见字段:会出现在物化manifest后的 JSON 中隐藏字段::不会。Java 没有内建对应概念因此框架引入约定每个对象类实现nonHiddenFields()返回应该出现在输出中的字段名集合集合之外的方法一律视为隐藏字段。基类 JsonnetObject.java 给出空实现public class JsonnetObject { public SetString nonHiddenFields() { return new HashSetString(){}; } }子类在覆写时先取父类集合再追加自己的可见字段例如 BaseTemplate.javapublic SetString nonHiddenFields() { SetString r super.nonHiddenFields(); r.addAll(Arrays.asList(apiVersion, kind, spec)); return r; }于是accessToken、image、extraEnv这些参数/隐藏字段方法虽然可被调用却不会出现在物化输出里。这个机制与 Jsonnet 解释器在物化阶段跳过隐藏字段的实现逻辑一一对应——在 VM 实现 core/vm.cpp 的objectFields中可以看到物化manifesting遍历对象字段时仅当字段不是ObjectField::HIDDEN才纳入输出。4.3 继承与覆写参数注入的两种写法Jsonnet 侧子模板 sub-template.jsonnet 使用对象拼接实现继承并注入参数(import base-template.libsonnet) { accessToken: xxxxx, image: gcr.io/cooltool-1009/pipeline_imagesha256:...., spec: { replicas: 2, } }顶层把子模板的accessToken、image覆写进基础模板相当于 Java 的方法覆写spec: { replicas: 2 }是字段级叠加只覆写spec对象里的replicas字段spec下其余结构spec.spec.containers等保持不变。Java 侧 SubTemplate.java 用继承覆写实现同样的效果public class SubTemplate extends BaseTemplate { public String accessToken() { return xxxxx; } public String image() { return gcr.io/cooltool-1009/pipeline_imagesha256:....; } public class SubTemplateSpec extends BaseTemplate.BaseTemplateSpec { public Object replicas() { return 2.0; } } public Object spec() { return new SubTemplateSpec(); } }SubTemplateSpec覆写BaseTemplateSpec的replicas()对应spec的叠加语义而spec()方法整体换成返回SubTemplateSpec实例。4.4 虚内部类用 Java 内部类表达 Jsonnet 的嵌套对象与$引用Jsonnet 的spec是一棵嵌套对象树内部通过$引用外层对象的字段见 base-template.libsonnet 中value: $.accessToken、image: $.image。Java 侧用内部类来保留这种内部引用外层的能力class Env0 extends JsonnetObject { public Object name() { return ACCESSTOKEN; } public Object value() { return BaseTemplate.this.accessToken(); } }BaseTemplate.this.accessToken()显式引用外层实例的字段等价于 Jsonnet 的$.accessToken。同理Container0.image()返回BaseTemplate.this.image()对应 Jsonnet 的image: $.image。这也解释了原文档Jsonnet 有虚内部类virtual inner classes的提法Java 内部类天然绑定到外层对象实例与 Jsonnet 嵌套对象通过$/super引用外层的语义非常接近这也是本示例能落在两语言交集内的关键原因。4.5 数组拼接Jsonnet 的与 Java 的手工实现Jsonnet 里env: [...] $.extraEnv一行完成基础环境变量数组 追加自定义数组的拼接。Java 没有数组级因此 BaseTemplate.java 中的env()用手工方式完成public Object[] env() { Object[] first new Object[]{ new Env0() }; Object[] second BaseTemplate.this.extraEnv(); Object[] result Arrays.copyOf(first, first.length second.length); System.arraycopy(second, 0, result, first.length, second.length); return result; }这段代码把 Jsonnet 语言内建的数组连接运算展开成了 Java 的标准库操作是语言特性到框架辅助函数翻译的典型例子。五、框架辅助函数物化Manifestation的实现Jsonnet 语言把把值序列化成 JSON 字符串称为物化manifestation是语言内建能力VM 中对应 core/vm.cpp 的manifestJson递归实现。Java 没有这种能力因此示例提供了两个辅助类5.1 JsonnetValue递归物化访问器JsonnetValue.java 的manifest(Object value)是一个按值类型分派的递归访问器恰好对应 Jsonnet 物化语义null→nullString→ 带引号字符串源码FIXME: does not escape the string注明没有做转义处理这是文档提到的两个自由度之一Double/Boolean→ 直接toString()Object[]→[ e1, e2, ... ]JsonnetObject→{ field: value, ... }其中字段集合来自nonHiddenFields()其余类型 → 抛RuntimeException(Got weird type: ...)与 Jsonnet函数不能物化进 JSON的运行时错误语义对应。5.2 反射调用字段方法物化对象时JsonnetValue对每个非隐藏字段名执行Method method obj.getClass().getMethod(field); Object fieldValue method.invoke(obj);即用反射按名字找到对应的无参方法并调用从而把Jsonnet 对象按字段名取值翻译成Java 按方法名反射调用。这一设计让子类覆写的方法如SubTemplate.replicas()在物化时自然被调用完整还原了 Jsonnet 的虚字段语义。5.3 Test入口与选择器Test.java 扮演 Jsonnet 命令行求值的角色main中直接JsonnetValue.manifest(new SubTemplate())并输出到 stdout相当于把sub-template.jsonnet的顶层表达式求值并物化。六、输出结果验证与两个已知自由度运行两侧命令后得到的 JSON 应与 sub-template.json 完全一致{ apiVersion: v1, kind: ReplicationController, spec: { replicas: 2, spec: { containers: [ { env: [ { name: ACCESSTOKEN, value: xxxxx } ], image: gcr.io/cooltool-1009/pipeline_imagesha256:...., name: twitter-to-redis } ] } } }可以看到accessToken、image、extraEnv这些隐藏字段没有出现在输出中而replicas从基础模板的 1 被覆写成了 2。原文档诚实声明了 Java 实现的两处自由度与 Jsonnet 输出存在格式差异、但不影响 JSON 语义字符串未做转义JsonnetValue对字符串直接\ value \若值含引号或反斜杠会与标准 JSON 不一致单行输出Java 直接输出一行紧凑 JSON靠| jsonnet -管道做格式化来对齐美观效果。七、适用边界与局限总结以本示例为窗口可以总结 Jsonnet 与 Java 互相翻译的完整边界可以翻译纯数据结构的嵌套对象、继承与覆写、隐藏字段参数、延迟语义下无副作用的部分本示例在交集内。Jsonnet 有而 Java 无法直接表达mixin用组合任意对象、虚内部类的部分动态行为以及依赖惰性求值顺序的程序。Java 有而 Jsonnet 无法表达可变状态、I/O、异常副作用等命令式行为。因此这套翻译方法适合的场景是在必须嵌入 JVM 生态如公司内部 Java 平台时把结构已知、纯声明式的 Jsonnet 配置模板用等价的 Java 类体系重新实现并借助jsonnet -保证输出格式与参考 JSON 对齐。若配置中大量使用 mixin 或惰性求值技巧则应优先考虑保留 Jsonnet 解释器而非翻译。八、延伸阅读仓库根目录 README.mdJsonnet 项目概览、构建与安装方式doc/learning/tutorial.htmlJsonnet 语言教程其中包含对象、继承与 mixin 的详细讲解doc/language/spec.html语言规范字段隐藏、物化语义的权威定义examples/mixins.jsonnetmixin 组合的典型示例case_studies/kubernetes/kube.libsonnet真实场景中把 Jsonnet 面向对象特性用于 Kubernetes 配置生成的案例与本示例同源core/vm.cppJsonnet 物化manifestation的底层实现可与 JsonnetValue.java 的物化逻辑对照阅读。赞分享编程语言模板引擎CLI【免费下载链接】jsonnetJsonnet - The data templating language项目地址https://gitcode.com/gh_mirrors/js/jsonnet点击查看免费下载相关推荐CANN/asc-devkit SIMD API资源管理GetBufHandlea nameZH CN_TOPIC_0000002051883238 /a 产品支持情况a namesection155人工智能深度学习算子库CANNAscendBitCPM4-CANN-8B安全与责任大语言模型使用的伦理指南BitCPM4 CANN 8B安全与责任大语言模型使用的伦理指南 BitCPM4 CANN 8B作为一款高效的大语言模型在带来强大AI能力的同时也需要使用揭秘Cartographer架构7大核心类构建SLAM系统的终极指南揭秘Cartographer架构7大核心类构建SLAM系统的终极指南 Cartographer是一个功能强大的实时同步定位与地图构建 SLAM 系统广泛应用机器人SLAM上一篇3分钟上手B站会员购抢票神器免费自动化购票终极指南下一篇猫抓插件终极指南三步搞定网页视频下载新手也能轻松上手创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考