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

如何在Python的Typer中正确获取CLI命令的JSON参数并实现JSON内容追加到文件的功能?

如何在Python的Typer中正确获取CLI命令的JSON参数并实现JSON内容追加到文件的功能?

嗨,我来帮你解决这个问题~你遇到的核心问题其实是终端的shell把你输入的引号给解析掉了,导致Typer拿到的JSON字符串格式不合法,没法用json.loads()正常解析。下面给你几个可行的解决办法,从简单调整命令到代码层面的处理都有:

一、调整终端命令的引号写法(最推荐)

不同终端的shell对引号的解析规则不一样,只要让shell完整传递带引号的JSON字符串给Typer就行:

  • Windows CMD:用双引号包裹整个JSON,内部的双引号用""转义
    python main.py "{\"Name\": \"Lily\"}" "D:\students.json"
    
  • Windows PowerShell:用单引号包裹整个JSON,内部直接用双引号
    python main.py '{"Name": "Lily"}' "D:\students.json"
    
  • Linux/macOS Bash:同样用单引号包裹整个JSON即可
    python main.py '{"Name": "Lily"}' "/path/to/students.json"
    

这样Typer就能收到完整的{"Name": "Lily"}字符串,直接用json.loads()解析就没问题了。

二、代码层面修复不合法的JSON字符串

如果不方便调整终端命令,可以写个小函数,把Typer收到的无引号键值对转换成合法JSON格式:

import typer
import json
import re

app = typer.Typer()

def fix_json_string(s):
    # 给无引号的键添加双引号
    s = re.sub(r'(\w+)\s*:', r'"\1":', s)
    # 给无引号的字符串值添加双引号(注意:这个逻辑对数字、布尔值可能不适用,需要根据你的场景调整)
    s = re.sub(r':\s*(\w+)', r': "\1"', s)
    return s

@app.command()
def append(argument: str, path: str):
    print(type(argument))
    print(argument)
    try:
        # 先修复JSON格式再解析
        fixed_arg = fix_json_string(argument)
        json_to_add = json.loads(fixed_arg)
        
        # 读取目标JSON文件
        with open(path, 'r', encoding='utf-8') as f:
            data = json.load(f)
        
        # 追加内容(假设文件内容是列表,如果是单个字典可自行调整逻辑)
        if isinstance(data, list):
            data.append(json_to_add)
        else:
            # 把单个字典转成列表再追加
            data = [data, json_to_add]
        
        # 写回文件,保留格式
        with open(path, 'w', encoding='utf-8') as f:
            json.dump(data, f, indent=2, ensure_ascii=False)
        
        typer.echo("内容成功追加到文件!")
    except json.JSONDecodeError as e:
        typer.echo(f"解析JSON失败:{str(e)}")
    except FileNotFoundError:
        typer.echo(f"错误:目标文件 {path} 不存在!")
    except Exception as e:
        typer.echo(f"发生未知错误:{str(e)}")

if __name__ == "__main__":
    app()

三、用Typer自定义类型自动解析JSON

可以定义一个自定义类型,让Typer在接收参数时自动完成JSON解析,代码更简洁:

import typer
import json
import re
from typing import Dict, Any

app = typer.Typer()

class JSONDict(Dict[str, Any]):
    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v):
        if isinstance(v, str):
            try:
                return json.loads(v)
            except json.JSONDecodeError:
                # 解析失败时尝试修复格式
                fixed_v = re.sub(r'(\w+)\s*:', r'"\1":', v)
                fixed_v = re.sub(r':\s*(\w+)', r': "\1"', fixed_v)
                return json.loads(fixed_v)
        elif isinstance(v, dict):
            return v
        else:
            raise typer.BadParameter("参数必须是合法的JSON字符串或字典")

@app.command()
def append(argument: JSONDict, path: str):
    # 这里argument已经是解析好的字典了
    try:
        with open(path, 'r', encoding='utf-8') as f:
            data = json.load(f)
        
        if isinstance(data, list):
            data.append(argument)
        else:
            data = [data, argument]
        
        with open(path, 'w', encoding='utf-8') as f:
            json.dump(data, f, indent=2, ensure_ascii=False)
        
        typer.echo("内容成功追加到文件!")
    except FileNotFoundError:
        typer.echo(f"错误:目标文件 {path} 不存在!")
    except Exception as e:
        typer.echo(f"发生未知错误:{str(e)}")

if __name__ == "__main__":
    app()

⚠️ 注意:代码里的修复逻辑只针对简单的键值对,如果你的JSON包含嵌套字典、数字、布尔值或者特殊字符,建议优先用第一种方法调整终端命令,确保传入的是标准JSON字符串。

备注:内容来源于stack exchange,提问作者Tamar .M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.17 09:33:16