Node.js JSON Schema Ajv依赖库逐步介绍验证类型和中文错误提示

news2024/11/19 5:55:56

在这里插入图片描述

在构建应用程序时,数据的有效性是至关重要的。为了确保传入的数据符合预期的格式和规范,我们可以使用 Ajv(Another JSON Schema Validator)进行验证。在这篇博文中,我们将从头开始学习 Ajv,逐步介绍验证类型和中文错误提示。

1. 什么是 Ajv?

Ajv 是一个用于验证 JSON 数据的库,它支持 JSON Schema 规范。通过定义 JSON Schema,我们可以描述数据的结构、类型和约束,然后使用 Ajv 来验证数据是否符合这些规范。

2. 安装 Ajv

首先,我们需要安装 Ajv 和一些相关的插件,打开终端并执行以下命令:

npm install ajv ajv-errors ajv-formats ajv-i18n koa @koa/router koa-bodyparser

这些插件包括错误处理插件 ajv-errors、格式验证插件 ajv-formats、中文错误提示插件 ajv-i18n 以及用于构建 Koa 应用的 koa@koa/routerkoa-bodyparser

3. 编写验证规范

我们将使用 Ajv 验证一个包含各种数据类型的 JSON 对象。以下是我们要验证的 JSON Schema:
为了添加中文注释,我们可以在 JSON Schema 的每个属性的注释中添加相关的中文描述。以下是带有中文注释的 JSON Schema:

const schema = {
  type: 'object',
  properties: {
    // 姓名,长度在3到20之间
    name: { type: 'string', minLength: 3, maxLength: 20, description: '姓名,长度在3到20之间' },
    
    // 年龄,必须是整数且不小于18
    age: { type: 'integer', minimum: 18, description: '年龄,必须是整数且不小于18' },
    
   	//余额,可以是浮点数
    balance: {
        type: "number",
        not: { type: "null" }
   	},
    // 爱好,是一个字符串数组
    hobbies: {
      type: 'array',
      items: { type: 'string' },
      description: '爱好,是一个字符串数组',
    },
    
    // 电子邮箱,必须符合邮箱格式
    email: { type: 'string', format: 'email', description: '电子邮箱,必须符合邮箱格式' },
    
    // 生日,必须符合日期格式
    birthday: { type: 'string', format: 'date', description: '生日,必须符合日期格式' },
    
    // 值,是一个包含数字和字符串的数组,且不能超过两个元素
    values: {
      type: 'array',
      items: [
        { type: 'integer', description: '第一个值是数字' },
        { type: 'string', description: '第二个值是字符串' },
      ],
      additionalItems: false, // 防止数组包含超过两个元素
      description: '值,是一个包含数字和字符串的数组,且不能超过两个元素',
    },
  
    // 地址列表,是一个包含城市和邮政编码的对象数组
    addresses: {
      type: 'array',
      items: {
        type: 'object',
        properties: {
          // 城市
          city: { type: 'string', description: '城市' },
          
          // 邮政编码
          zipCode: { type: 'string', description: '邮政编码' },
        },
        required: ['city', 'zipCode'],
      },
      description: '地址列表,是一个包含城市和邮政编码的对象数组',
    },
  },
  required: ['name', 'age', 'values', 'addresses', 'birthday', 'email'],
};

在这个例子中,我在每个属性的 description 中添加了中文注释,以描述该属性的含义和约束。这将有助于其他开发人员理解和维护这个 JSON Schema。

这个 JSON Schema 定义了一个对象,其中包含了字符串、整数、数组、邮箱、日期等各种类型的属性,并设置了一些约束条件。
如字符串、整数、数组、对象等。然而,还有一些其他可能用到的验证类型,具体取决于你的应用需求。以下是一些可能有用的额外验证类型和示例:

  1. Boolean 类型:

    const schemaWithBoolean = {
      type: 'object',
      properties: {
        isActive: { type: 'boolean' },
      },
      required: ['isActive'],
    };
    
  2. Null 类型:

    const schemaWithNull = {
      type: 'object',
      properties: {
        description: { type: 'null' },
      },
      required: ['description'],
    };
    
  3. 数字范围:

    const schemaWithNumberRange = {
      type: 'object',
      properties: {
        quantity: { type: 'integer', minimum: 0, maximum: 100 },
      },
      required: ['quantity'],
    };
    
  4. 字符串模式:

    const schemaWithStringPattern = {
      type: 'object',
      properties: {
        code: { type: 'string', pattern: '^ABC\\d{3}$' }, // 匹配以"ABC"开头,后跟三个数字的字符串
      },
      required: ['code'],
    };
    
  5. 枚举值:

    const schemaWithEnum = {
      type: 'object',
      properties: {
        gender: { type: 'string', enum: ['male', 'female', 'other'] },
      },
      required: ['gender'],
    };
    
  6. 数组长度:

    const schemaWithArrayLength = {
      type: 'object',
      properties: {
        tags: { type: 'array', minItems: 1, maxItems: 5 },
      },
      required: ['tags'],
    };
    

ajv-formats 是 Ajv 的一个插件,它提供了一些常见的格式校验,使得我们可以更方便地验证数据是否符合特定的格式要求。以下是该插件提供的一些格式校验以及它们的用法示例:

  1. date-time: 校验日期时间格式。
const schema = {
  type: 'string',
  format: 'date-time',
};

// 示例数据
const validDateTime = '2022-02-14T10:30:00Z';
  1. time: 校验时间格式。
const schema = {
  type: 'string',
  format: 'time',
};

// 示例数据
const validTime = '10:30:00';
  1. date: 校验日期格式。
const schema = {
  type: 'string',
  format: 'date',
};

// 示例数据
const validDate = '2022-02-14';
  1. email: 校验邮箱格式。
const schema = {
  type: 'string',
  format: 'email',
};

// 示例数据
const validEmail = 'example@email.com';
  1. hostname: 校验主机名格式。
const schema = {
  type: 'string',
  format: 'hostname',
};

// 示例数据
const validHostname = 'www.example.com';
  1. ipv4: 校验 IPv4 地址格式。
const schema = {
  type: 'string',
  format: 'ipv4',
};

// 示例数据
const validIPv4 = '192.168.0.1';
  1. ipv6: 校验 IPv6 地址格式。
const schema = {
  type: 'string',
  format: 'ipv6',
};

// 示例数据
const validIPv6 = '2001:0db8:85a3:0000:0000:8a2e:0370:7334';
  1. uri: 校验 URI 格式。
const schema = {
  type: 'string',
  format: 'uri',
};

// 示例数据
const validURI = 'https://www.example.com';
  1. uri-reference: 校验 URI 引用格式。
const schema = {
  type: 'string',
  format: 'uri-reference',
};

// 示例数据
const validURIReference = '/path/to/resource';
  1. uri-template: 校验 URI 模板格式。
const schema = {
  type: 'string',
  format: 'uri-template',
};

// 示例数据
const validURITemplate = '/users/{id}';
  1. json-pointer: 校验 JSON 指针格式。
const schema = {
  type: 'string',
  format: 'json-pointer',
};

// 示例数据
const validJSONPointer = '/path/to/property';
  1. relative-json-pointer: 校验相对 JSON 指针格式。
const schema = {
  type: 'string',
  format: 'relative-json-pointer',
};

// 示例数据
const validRelativeJSONPointer = '1/child';
  1. regex: 校验正则表达式。
const schema = {
  type: 'string',
  format: 'regex',
  pattern: '^\\d{3}-\\d{2}-\\d{4}$', // 正则表达式
};

// 示例数据
const validRegex = '123-45-6789';

这些格式校验使得我们在验证数据时更加灵活,能够直接使用预定义的格式进行验证,提高了数据验证的准确性和可读性。
这些是一些可能有用的验证类型和约束。根据你的具体需求,你可能需要进一步了解 JSON Schema 的其他验证选项。 JSON Schema 支持丰富的验证功能,以满足各种数据模型的需求。

4. 中间件:验证请求数据

接下来,我们将创建一个 Koa 中间件来验证请求数据是否符合上述定义的 JSON Schema。在中间件中,我们使用 Ajv 编译 JSON Schema 并验证请求数据:

const Ajv = require('ajv');
const localize = require('ajv-i18n');
const ajv = new Ajv({ allErrors: true });
require('ajv-errors')(ajv);
require('ajv-formats')(ajv);

// 中间件:校验请求数据
const validateMiddleware = async (ctx, next) => {
  const data = ctx.request.body;

  // 编译 JSON Schema
  const validate = ajv.compile(schema);

  // 验证数据是否符合 JSON Schema
  const isValid = validate(data);

  if (!isValid) {
    // 指定语言为中文
    localize.zh(validate.errors);
    // 设置 errorsText 选项为中文
    const errorText = ajv.errorsText(validate.errors, { separator: '\n', dataVar: 'data' });

    ctx.status = 400;
    ctx.body = {
      error: 'Invalid data',
      details: errorText,
    };
    return;
  }

  await next();
};

在这个中间件中,我们使用 ajv.errorsText 来生成错误文本,同时将 dataVar 选项设置为 'data',以确保在错误消息中使用中文。如果数据验证不通过,中间件将返回包含中文错误信息的 400 错误响应。

5. 应用 Koa 路由

最后,我们将创建一个 Koa 应用,使用上述中间件处理 /api/data 路由的 POST 请求:

const Koa = require('koa');
const Router = require('@koa/router');
const bodyParser = require('koa-bodyparser');

const app = new Koa();
const router = new Router();

// 使用中间件
app.use(bodyParser());

// 路由处理
router.post('/api/data', validateMiddleware, async (ctx) => {
  ctx.body = { message: 'Data is valid!' };
});

// 添加路由
app.use(router.routes());
app.use(router.allowedMethods());

// 启动应用
const PORT = 3000;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

现在,我们的 Koa 应用已经可以验证请求数据,并返回相应的中文错误信息了。

通过这篇博文,我们逐步学习了如何使用 Ajv 验证不同类型的数据,并在 Koa 应用中实现中文错误提示。这为构建健壮的应用程序提供了强大的数据验证工具。

完整验证接口数据示例代码

const Koa = require('koa');
const Router = require('@koa/router');
const bodyParser = require('koa-bodyparser');
const Ajv = require('ajv');
const localize = require("ajv-i18n");

const ajv = new Ajv({ allErrors: true });
require('ajv-errors')(ajv);
require('ajv-formats')(ajv);

const app = new Koa();
const router = new Router();

// 定义 JSON Schema
const schema = {
    type: 'object',
    properties: {
        // 姓名,长度在3到20之间
        name: { type: 'string', minLength: 3, maxLength: 20, description: '姓名,长度在3到20之间' },

        // 年龄,必须是整数且不小于18
        age: { type: 'integer', minimum: 18, description: '年龄,必须是整数且不小于18' },

        // 爱好,是一个字符串数组
        hobbies: {
            type: 'array',
            items: { type: 'string' },
            description: '爱好,是一个字符串数组',
        },

        // 电子邮箱,必须符合邮箱格式
        email: { type: 'string', format: 'email', description: '电子邮箱,必须符合邮箱格式' },

        // 生日,必须符合日期格式
        birthday: { type: 'string', format: 'date', description: '生日,必须符合日期格式' },

        // 值,是一个包含数字和字符串的数组,且不能超过两个元素
        values: {
            type: 'array',
            items: [
                { type: 'integer', description: '第一个值是数字' },
                { type: 'string', description: '第二个值是字符串' },
            ],
            additionalItems: false, // 防止数组包含超过两个元素
            description: '值,是一个包含数字和字符串的数组,且不能超过两个元素',
        },

        // 地址列表,是一个包含城市和邮政编码的对象数组
        addresses: {
            type: 'array',
            items: {
                type: 'object',
                properties: {
                    // 城市
                    city: { type: 'string', description: '城市' },

                    // 邮政编码
                    zipCode: { type: 'string', description: '邮政编码' },
                },
                required: ['city', 'zipCode'],
            },
            description: '地址列表,是一个包含城市和邮政编码的对象数组',
        },
    },
    required: ['name', 'age', 'values', 'addresses', 'birthday', 'email'],
};
// 中间件:校验请求数据
const validateMiddleware = async (ctx, next) => {
    const data = ctx.request.body;

    // 编译 JSON Schema
    const validate = ajv.compile(schema);

    // 验证数据是否符合 JSON Schema
    const isValid = validate(data);

    if (!isValid) {
        // 指定语言为中文
        localize.zh(validate.errors);
        // 设置 errorsText 选项为中文
        const errorText = ajv.errorsText(validate.errors, { separator: '\n', dataVar: 'data' });

        ctx.status = 400;
        ctx.body = {
            error: 'Invalid data',
            details:errorText,
        };
        return;
    }

    await next();
};

// 使用中间件
app.use(bodyParser());

// 路由处理
router.post('/api/data', validateMiddleware, async (ctx) => {
    ctx.body = { message: '数据验证通过' };
});

// 添加路由
app.use(router.routes());
app.use(router.allowedMethods());

// 启动应用
const PORT = 3000;
app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});

HTTP 请求示例数据

POST /api/data HTTP/1.1
Host: 127.0.0.1:3000
Content-Type: application/json
Content-Length: 313

{
  "name":"xiongmingcai",
   "email":"xiongmingcai(#)gmail.com",
  "age":30,
  "birthday":"1990-05-15",
  "hobbies":["唱跳","RAP","打篮球"],
    "values":[1,"字符串"],
    "addresses":[{
        "city":"北京",
        "zipCode":"000000"
    },{
        "city":"长沙",
        "zipCode":"000000"
    }
    ]
}

进阶用法 使用 $ref 引用其他 JSON Schema

const mainSchema = {
  $id: 'mainSchema',
  type: 'object',
  properties: {
    person: { $ref: 'personSchema' },
    address: { $ref: 'addressSchema' },
  },
};

const personSchema = {
  $id: 'personSchema',
  type: 'object',
  properties: {
    name: { type: 'string' },
    age: { type: 'integer' },
  },
  required: ['name', 'age'],
};

const addressSchema = {
  $id: 'addressSchema',
  type: 'object',
  properties: {
    city: { type: 'string' },
    zipCode: { type: 'string' },
  },
  required: ['city', 'zipCode'],
};

const ajv = new Ajv();
ajv.addSchema([mainSchema, personSchema, addressSchema]);

const validateMain = ajv.getSchema('mainSchema');
const data = {
  person: { name: 'John', age: 25 },
  address: { city: 'New York', zipCode: '10001' },
};

const isValid = validateMain(data);

if (isValid) {
  console.log('Data is valid!');
} else {
  console.error('Data is invalid!');
  console.error(validateMain.errors);
}

组合关键字(AJV allOf、anyOf、oneOf、not)

AJV 提供了一些组合关键字,如 allOfanyOfoneOfnot,用于在 JSON Schema 中表示更复杂的逻辑关系。以下是这些关键字的使用示例:

1. allOf:所有条件都必须匹配

import Ajv from 'ajv';

// 创建 Ajv 实例
const ajv = new Ajv();

// 定义 JSON Schema 使用 allOf
const schema = {
  allOf: [
    { type: 'object', required: ['name'] },
    { type: 'object', properties: { age: { type: 'number' } } },
  ],
};

// 示例数据
const validData = { name: 'John', age: 25 };

// 验证数据是否符合 JSON Schema
const validate = ajv.compile(schema);
const isValid = validate(validData);

console.log(isValid); // 输出 true

2. anyOf:至少一个条件匹配

import Ajv from 'ajv';

// 创建 Ajv 实例
const ajv = new Ajv();

// 定义 JSON Schema 使用 anyOf
const schema = {
  anyOf: [
    { type: 'object', required: ['name'] },
    { type: 'object', properties: { age: { type: 'number' } } },
  ],
};

// 示例数据
const validData = { name: 'John' };

// 验证数据是否符合 JSON Schema
const validate = ajv.compile(schema);
const isValid = validate(validData);

console.log(isValid); // 输出 true

3. oneOf:只有一个条件匹配

import Ajv from 'ajv';

// 创建 Ajv 实例
const ajv = new Ajv();

// 定义 JSON Schema 使用 oneOf
const schema = {
  oneOf: [
    { type: 'object', required: ['name'] },
    { type: 'object', properties: { age: { type: 'number' } } },
  ],
};

// 示例数据
const validData = { name: 'John' };

// 验证数据是否符合 JSON Schema
const validate = ajv.compile(schema);
const isValid = validate(validData);

console.log(isValid); // 输出 true

4. not:条件不能匹配

import Ajv from 'ajv';

// 创建 Ajv 实例
const ajv = new Ajv();

// 定义 JSON Schema 使用 not
const schema = {
  not: {
    type: 'object',
    properties: { age: { type: 'number' } },
  },
};

// 示例数据
const invalidData = { age: 25 };

// 验证数据是否符合 JSON Schema
const validate = ajv.compile(schema);
const isValid = validate(invalidData);

console.log(isValid); // 输出 false

这些关键字允许你构建更复杂的验证规则,以满足特定的数据结构和逻辑需求。在实际应用中,可以根据具体情况组合使用这些关键字。。

如何设置自定义AJV关键字?( custom AJV keyword)

Ajv 允许你定义自己的 JSON Schema 关键字,以扩展验证功能。
在 TypeScript 环境下,你可以使用以下方式使用自定义关键字:

import Ajv, { AnySchemaObject } from 'ajv';

// 创建 Ajv 实例
const ajv = new Ajv();

// 自定义关键字定义
let kwdOrDef: FuncKeywordDefinition = {
  keyword: 'eachPropIsTrue',       // 关键字的名称
  type: 'object',                  // 关键字适用的 JSON 数据类型
  schemaType: 'boolean',           // 关键字的 schema 类型
  compile: (schema: boolean, parentSchema: AnySchemaObject) => {
    // 编译函数,用于生成验证函数
    return (data: Record<string, any>) => {
      // 验证函数逻辑
      return Object.values(data).every((value) => !!value);
    };
  },
};

// 添加自定义关键字到 Ajv 实例中
ajv.addKeyword(kwdOrDef);

// 定义 JSON Schema
const schema = {
  type: 'object',
  eachPropIsTrue: true,
};

// 示例数据
const validData = {
  prop1: true,
  prop2: false,
  prop3: true,
};

// 验证数据是否符合 JSON Schema
const validate = ajv.compile(schema);
const isValid = validate(validData);

console.log(isValid); // 输出 false,因为 prop2 是 false

在上述示例中:

  1. 引入 Ajv 并使用 AnySchemaObject 接口。
  2. 使用 ajv.addKeyword 添加自定义关键字。
  3. 在 JSON Schema 中使用自定义关键字 eachPropIsTrue
  4. 编译 JSON Schema 并验证数据是否符合。

这样,你就可以在 TypeScript 环境下使用自定义关键字了。确保在编写 TypeScript 代码时,按照 TypeScript 的语法规范进行书写。

自定义格式(custom AJV format)

要在 Ajv 中添加自定义格式来验证身份证号码,你需要使用 ajv.addFormat 方法并提供一个验证函数。以下是一个简单的示例,演示了如何验证身份证号码的基本格式:

import Ajv from 'ajv';

// 创建 Ajv 实例
const ajv = new Ajv();

// 添加身份证号码格式验证
ajv.addFormat('idNumber', (data) => {
  // 简单示例:验证身份证号码为18位数字
  const regex = /^[0-9]{18}$/;
  return regex.test(data);
});

// 定义 JSON Schema
const schema = {
  type: 'string',
  format: 'idNumber',
};

// 示例数据
const validIdNumber = '123456789012345678';
const invalidIdNumber = '1234567890'; // 不符合格式

// 验证数据是否符合 JSON Schema
const validate = ajv.compile(schema);

console.log(validate(validIdNumber)); // 输出 true
console.log(validate(invalidIdNumber)); // 输出 false

在这个示例中,ajv.addFormat 方法添加了一个名为 'idNumber' 的自定义格式,它使用了一个简单的正则表达式来验证身份证号码是否为18位数字。你可以根据实际需求更改验证逻辑,例如验证生日、地区等详细信息。

请注意,身份证号码的验证逻辑因国家而异,这里只是一个简单的示例。在实际应用中,你可能需要使用更复杂的验证规则来确保身份证号码的准确性和合法性。

异步验证:(Ajv compileAsync)

对于异步操作,Ajv 提供了 compileAsync 方法来编译异步的 JSON Schema。
https://ajv.js.org/guide/async-validation.html
官网示例代码 没研究明白

const ajv = new Ajv()

ajv.addKeyword({
  keyword: "idExists",
  async: true,
  type: "number",
  validate: checkIdExists,
})

async function checkIdExists(schema, data) {
  // this is just an example, you would want to avoid SQL injection in your code
  const rows = await sql(`SELECT id FROM ${schema.table} WHERE id = ${data}`)
  return !!rows.length // true if record is found
}

const schema = {
  $async: true,
  properties: {
    userId: {
      type: "integer",
      idExists: {table: "users"},
    },
    postId: {
      type: "integer",
      idExists: {table: "posts"},
    },
  },
}

const validate = ajv.compile(schema)

validate({userId: 1, postId: 19})
  .then(function (data) {
    console.log("Data is valid", data) // { userId: 1, postId: 19 }
  })
  .catch(function (err) {
    if (!(err instanceof Ajv.ValidationError)) throw err
    // data is invalid
    console.log("Validation errors:", err.errors)
  })

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1435024.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用webstorm调试vue 2 项目

学习目标&#xff1a; 使用webstorm调试vue 2 项目 笔者环境&#xff1a; npm 6.14.12 webstorm 2023.1 vue 2 学习内容&#xff1a; 例如&#xff1a; 正常启动npm 项目 配置javaScruot dubug 配置你的项目地址就好 使用dubug运行你配置的调式页 问题 如果进入了js页无…

模拟被观察物体的位置和方向

开发环境&#xff1a; Windows 11 家庭中文版Microsoft Visual Studio Community 2019VTK-9.3.0.rc0vtk-example demo解决问题&#xff1a;模拟被观察物体的位置和方向&#xff0c;以帮助用户理解相机在观察特定对象时的位置和朝向。vtkCameraOrientationWidget 模拟的是被观察…

【Iceberg学习四】Evolution和Maintenance在Iceberg的实现

Evolution Iceberg 支持就底表演化。您可以像 SQL 一样演化表结构——即使是嵌套结构——或者当数据量变化时改变分区布局。Iceberg 不需要像重写表数据或迁移到新表这样耗费资源的操作。 例如&#xff0c;Hive 表的分区布局无法更改&#xff0c;因此从每日分区布局变更到每小…

MySQL查询优化技巧和10个案例展示

优化MySQL查询的实战技巧&#xff1a; **避免使用SELECT ***&#xff1a;只获取需要的列&#xff0c;这样可以减少数据传输量&#xff0c;提高查询效率。使用索引&#xff1a;为查询频繁的列创建索引&#xff0c;可以显著提高查询速度。但请注意&#xff0c;索引并非万能&…

Docker下安装GitLab

极狐GitLab Docker 镜像 | 极狐GitLab 安装所需最小配置 内存至少4G 系统内核至少3.10以上 uname -r 命令可以查看系统内核版本 安装Docker 1.更新 yum源 yum update 2.安装依赖(如果在操作第三步的时候提示yum-config-manager 未找到命令 就安装下面依赖) yum instal…

Linux【docker 设置阿里源】

文章目录 一、查看本地docker的镜像配置二、配置阿里镜像三、检查配置 一、查看本地docker的镜像配置 docker info一般没有配置过是不会出现Registry字段的 二、配置阿里镜像 直接执行下面代码即可&#xff0c;安装1.10.0以上版本的Docker客户端都会有/etc/docker 1.建立配置…

从Kafka系统中读取消息数据——消费

从Kafka系统中读取消息数据——消费 消费 Kafka 集群中的主题消息检查消费者是不是单线程主题如何自动获取分区和手动分配分区subscribe实现订阅&#xff08;自动获取分区&#xff09;assign&#xff08;手动分配分区&#xff09; 反序列化主题消息反序列化一个类.演示 Kafka 自…

ubuntu22.04@laptop OpenCV Get Started: 001_reading_displaying_write_image

ubuntu22.04laptop OpenCV Get Started: 001_reading_displaying_write_image 1. 源由2. Read/Display/Write应用Demo2.1 C应用Demo2.2 Python应用Demo 3. 过程分析3.1 导入OpenCV库3.2 读取图像文件3.3 显示图像3.4 保存图像文件 4. 总结5. 参考资料 1. 源由 读、写、显示图像…

annaconda如何切换当前python环境

annaconda默认的python环境是base&#xff1a; 把各种项目的依赖都安装到base环境中不是一个好的习惯&#xff0c;比如说我们做爬虫项目和做自动化测试项目等所需要的依赖是不一样的&#xff0c;我们可以将为每个项目创建自己的环境&#xff0c;在各自的环境中安装自己的依赖&…

javaEE - 23( 21000 字 Servlet 入门 -1 )

一&#xff1a;Servlet 1.1 Servlet 是什么 Servlet 是一种实现动态页面的技术. 是一组 Tomcat 提供给程序猿的 API, 帮助程序猿简单高效的开发一个 web app. 构建动态页面的技术有很多, 每种语言都有一些相关的库/框架来做这件事&#xff0c;Servlet 就是 Tomcat 这个 HTTP…

IntelliJ IDE 插件开发 | (六)内部模式的使用

系列文章 IntelliJ IDE 插件开发 |&#xff08;一&#xff09;快速入门IntelliJ IDE 插件开发 |&#xff08;二&#xff09;UI 界面与数据持久化IntelliJ IDE 插件开发 |&#xff08;三&#xff09;消息通知与事件监听IntelliJ IDE 插件开发 |&#xff08;四&#xff09;来查收…

【新书推荐】6.2 else if语句

本节必须掌握的知识点&#xff1a; 示例代码二十 代码分析 汇编解析 ■if语句表达形式3 if(表达式1) statement1 else if(表达式2) statement2 else if(表达式3) statement3 …… else statementN 解析&#xff1a; 如果表达式1非0&#xff0c;则执行statement1&#…

SpringBoot 全局异常处理

介绍 如果代码没有做异常处理&#xff0c;就会报框架错误&#xff0c;而这种格式不符合REST风格&#xff0c;也可以在每一个接口添加 try{ } catch { } 捕获异常&#xff0c;但是会非常的繁琐&#xff0c;这时候可以使用全局异常处理。 统一响应类 Data NoArgsConstructor …

地下停车场智慧监查系统:科技让停车更智能

随着城市化进程的加速&#xff0c;停车难成为了许多城市居民的痛点。而地下停车场作为解决停车难问题的重要手段&#xff0c;其安全性和便捷性也成为了人们关注的焦点。为了解决这一问题&#xff0c;山海鲸可视化搭建的地下停车场智慧监查系统应运而生&#xff0c;为车主们提供…

uniapp踩坑之项目:简易版不同角色显示不一样的tabbar和页面

1. pages下创建三个不同用户身份的“我的”页面。 显示第几个tabbar&#xff0c;0是管理员 1是财务 2是司机 2. 在uni_modules文件夹创建底部导航cc-myTabbar文件夹&#xff0c;在cc-myTabbar文件夹创建components文件夹&#xff0c;在components文件夹创建cc-myTabbar.vue组件…

js的属性描述符

目录 属性描述符数据属性描述符writableenumerableconfigurablevalue 存取属性描述符getset关于get与set 通过Object.defineProperty实现响应式 属性描述符 在ES5之前&#xff0c;我们虽然能通过字面量的形式直接在对象上添加或修改属性&#xff0c;但终究不能对其进行更加精细…

给数据分列的案例操作-LH-camera

简单介绍 利用xlrd读取xls数据&#xff0c;给xls表添加"所属平台"字段分列&#xff08;以最长分列为准&#xff0c;填充空格&#xff09;。利用openpyxl&#xff0c;将分列后数据存储到xls文件中&#xff0c;名字格式固定。 具体代码 # 用户原始表格存放位置&…

Polar-Net:通过 OCTA(光学相干断层扫描血管成像)检测阿尔茨海默病

通过OCTA&#xff08;光学相干断层扫描血管成像&#xff09;检测阿尔茨海默病 主问题&#xff1a;如何通过OCTA图像有效地检测阿尔茨海默病&#xff1f;子问题1&#xff1a;如何在深度学习模型中模拟临床实践中常用的区域基础分析方法&#xff1f;子问题2&#xff1a;如何在网络…

Python算法题集_环形链表

Python算法题集_环形链表 题234&#xff1a;环形链表1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【集合检索】2) 改进版一【字典检测】3) 改进版二【双指针】 4. 最优算法 本文为Python算法题集之一的代码示例 题234&#xff1a;环形链表 …

掌握CSS网格函数fit-content()的妙用

CSS网格布局是一种强大的布局系统&#xff0c;它提供了灵活的网格化设计能力。其中&#xff0c;fit-content()函数是一项重要的功能&#xff0c;它可以帮助我们在网格容器中自动调整网格项的尺寸。本文将详细讲解fit-content()函数的使用方法及其常见应用场景&#xff0c;助你掌…