Schematics支持嵌套对象吗

wen python案例 15

本文目录导读:

Schematics支持嵌套对象吗

  1. 具体支持的方式:
  2. 示例(修改 package.json 中的嵌套对象)
  3. 实际示例:修改 angular.json 中的 project 配置
  4. 社区和库支持

是的,Schematics(尤其是在 Angular 和现代 Web 开发上下文中)支持嵌套对象

核心机制是:使用 JsonPointer(JSON 指针)语法来指定嵌套属性的路径

在 Schematics 中,当你操作一个 JsonObjectpackage.jsonangular.json)时,你可以通过路径字符串来访问或修改深层嵌套的属性,这个路径字符串遵循 JSON Pointer 标准,使用斜杠 分隔每一层级。

具体支持的方式:

  1. 路径表达式:使用 'key/subkey/subsubkey' 的格式。
  2. 属性操作getsetremoveappend 等操作都支持路径字符串。

示例(修改 package.json 中的嵌套对象)

假设 treeTree 对象,hostHost 对象。

场景 1:读取嵌套值

// 假设 package.json 中有:
// {
//   "builders": {
//     "my-builder": {
//       "implementation": "./dist/my-builder.js"
//     }
//   }
// }
const packageJson = host.readJson('package.json') as any;
// 直接通过属性链访问嵌套对象
const builderImpl = packageJson.builders?.['my-builder']?.implementation;
console.log(builderImpl); // 输出: ./dist/my-builder.js

场景 2:使用路径修改嵌套值(推荐方式)

import { JsonArray, JsonObject, workspaces } from '@angular-devkit/core';
function updateNestedConfig(host: workspaces.WorkspaceHost) {
  const config = host.readJson('angular.json') as JsonObject;
  // 路径 'projects.my-app.architect.build.options.outputPath'
  // 指向 angular.json 中:
  // projects -> my-app -> architect -> build -> options -> outputPath 的值
  const currentPath = config['projects']['my-app']['architect']['build']['options']['outputPath'];
  // 或者使用更安全的方式(需要自己实现递归查找)
  const newConfig = {
    ...config,
    projects: {
      ...config['projects'],
      'my-app': {
        ...(config['projects'] as any)['my-app'],
        architect: {
          ...(config['projects'] as any)['my-app']?.['architect'],
          build: {
            ...(config['projects'] as any)['my-app']?.['architect']?.['build'],
            options: {
              ...(config['projects'] as any)['my-app']?.['architect']?.['build']?.options,
              outputPath: 'dist/my-new-output'
            }
          }
        }
      }
    }
  };
  host.overwrite('angular.json', JSON.stringify(newConfig, null, 2));
}

场景 3:使用 JsonPointer 库(更简洁)

Schematics 内部依赖 jsonc-parser,但它也支持 @angular-devkit/core 中的 JsonPointer 类(虽然不常用作 API)。

实际更常见的做法是:手动递归或使用 Lodash 的 set/get 函数

// 如果项目中安装了 lodash(或使用 set/get 函数)
import * as _ from 'lodash';
function setNestedValue(obj: any, path: string, value: any) {
  // path = "projects.my-app.architect.build.options.outputPath"  (点号分隔)
  // 或者 path = "projects/my-app/architect/build/options/outputPath" (斜杠分隔,需转换)
  const pathArray = path.replace(/\//g, '.').split('.');
  _.set(obj, pathArray, value);
}
// 使用
const config = host.readJson('angular.json') as any;
setNestedValue(config, 'projects.my-app.architect.build.options.outputPath', 'dist/new-path');
host.overwrite('angular.json', JSON.stringify(config, null, 2));
特性 说明
支持类型 任何可以被序列化为 JSON 的对象(Object、Array、基本类型)
路径语法 使用点号 或斜杠 作为分隔符(在 JSON Pointer 中是 ,但在 JS 中常用 )
数组支持 支持通过索引访问数组元素,'arrayProp.0.name''arrayProp/0/name'
安全注意事项 路径中的每一级都必须存在,如果中间级不存在,需要自行创建对象或使用 _.set 等库

实际示例:修改 angular.json 中的 project 配置

这是一个 Schematics 中非常常见的操作:

// schematic 规则
export function mySchematic(options: any): Rule {
  return (tree: Tree, context: SchematicContext) => {
    // 读取 angular.json
    const angularJsonBuffer = tree.read('angular.json');
    if (!angularJsonBuffer) {
      context.logger.error('Could not read angular.json file.');
      return tree;
    }
    const angularJson = JSON.parse(angularJsonBuffer.toString());
    // 嵌套操作:修改某个项目的 builder 的 options
    const projectName = options.project || 'defaultProject';
    if (angularJson.projects && angularJson.projects[projectName]) {
      // 确保嵌套路径存在
      if (!angularJson.projects[projectName].architect) {
        angularJson.projects[projectName].architect = {};
      }
      if (!angularJson.projects[projectName].architect.build) {
        angularJson.projects[projectName].architect.build = {};
      }
      if (!angularJson.projects[projectName].architect.build.options) {
        angularJson.projects[projectName].architect.build.options = {};
      }
      // 修改嵌套属性
      angularJson.projects[projectName].architect.build.options.outputPath = options.outputPath || 'dist/my-app';
    }
    // 写回文件
    tree.overwrite('angular.json', JSON.stringify(angularJson, null, 2));
    return tree;
  };
}

社区和库支持

  • @angular-devkit/core:提供 JsonObjectJsonArray 类型,但不提供内置的简洁嵌套路径 API。
  • jsonc-parser:Schematics 内部使用,可以处理带注释的 JSON,但访问嵌套属性仍需手动。
  • 推荐:在自定义 Schematics 中,直接使用 JavaScript 的原生对象操作(如 obj.a.b.c)或 lodash.set / lodash.get 是最清晰、最简洁的方式。

Schematics 完全支持嵌套对象,但需要你通过标准的 JavaScript 对象操作或辅助库来实现嵌套路径的访问与修改,框架本身没有提供一种特殊的“嵌套对象路径 DSL”(领域特定语言),但操作普通的嵌入式对象在 JavaScript 中非常直接。

抱歉,评论功能暂时关闭!