基于字符串生成json转换的类型

该代码示例展示了如何在Java中处理复杂的Json字符串,通过Fastjson库解析具有多层嵌套的参数化类型。方法`getTypes2`和`getTypes3`用于分析和构建Json类型,使用栈数据结构处理类型定义中的层次关系。同时,`main`方法演示了如何将解析后的类型应用于Json字符串解析。
Json类型分析

场景: 基于用户配置的字符串,生成json装换的类型

package com.soul.base.test;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.util.ParameterizedTypeImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.lang.reflect.Type;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public class TypeAnalysisTest {

    public static void main(String[] args) throws Exception {

        getTypes2("A");
        System.out.println();
        getTypes2("A<B>");
        System.out.println();

        getTypes2("A<B,C>");
        System.out.println();
        getTypes2("A<B,C,D>");
        System.out.println();
        getTypes2("A<B<B1,B2>,C>");
        System.out.println();
        getTypes2("A<B,C<C1,C2>>");
        System.out.println();

        getTypes2("A<B<B1,B2,B3>>");
        System.out.println();
        getTypes2("A<B,C<C1,C2,C3>>");
        System.out.println();
        getTypes2("A<B<B1,B2,B3>,C>");
        System.out.println();

        getTypes2("A<B,C<C1<C2<C3>>>,D<D1<D2<D3>>>>");
        System.out.println();
        getTypes2("A<B,C<C1,C2,C3>,D<D1<D2<D3>>>>");
        System.out.println();
        getTypes2("A<B<B1,B2,B3>,C<C1,C2,C3>,D<D1<D2<D3>>>>");
        System.out.println();
        getTypes2("A<B<B1,B2,B3>,C<C1<C2<C3>>>,D<D1<D2<D3>>>>");
        System.out.println();
        getTypes2("A<B<B1<B2<B3>>>,C<C1<C2<C3>>>,D<D1<D2<D3>>>>");
        System.out.println();
        getTypes2("A<B<B1<B2<B3>>>,C<C1<C2<C3>,C2<C3>>>,D<D1<D2<D3>>>>");
        System.out.println();
        getTypes2("A<B<B1<B2<B3>>>,C,D>");
        System.out.println();


        String responseStr = "{\"A\":{\"A1\":[\"A2\",\"A3\",\"A4\"]},\"B\":{\"B1\":null},\"C\":null}";
        String types = "java.util.Map<java.lang.String,java.util.Map<java.lang.String,java.util.List<java.lang.String>>>";
        ParameterizedTypeImpl types3 = getTypes3(types);
        Map<String,Map<String,List<String>>> map = JSONObject.parseObject(responseStr, types3);
        System.out.println(map.get("A"));
        System.out.println(map.get("A").get("A1").get(0));
        System.out.println(map.get("B"));
        System.out.println(map.get("C"));

    }

    public static LinkedList<String> init(String className) {
        LinkedList<String> levelList = new LinkedList<>();
        levelList.add(className);
        return levelList;
    }

    public static void getTypes2(String types) {

        //截取类型的开始下标
        int startIndex = 0;
        //截取类型的结束下标
        int endIndex;
        //上一次遇到的操作符号
        char lastSymbol = '<';

        Stack<List<String>> clazzStack = new Stack<>();
        if (!types.contains("<")){
            clazzStack.push(init(types));
        }

        types = types.replaceAll("\\s+", "");
        for (int i = 0; i < types.length(); i++) {
            endIndex = i;
            char charAt = types.charAt(i);
            // 注意: 每一次处理的是操作符号左边的数据
            if (charAt == '<') {
                // <开始符号, 压入元素
                if (lastSymbol == '<'){
                    //<左侧为新层级且仅有一个元素,新建层并压入
                    clazzStack.push(init(types.substring(startIndex, endIndex)));
                } else if (lastSymbol == ',') {
                    //<左侧为,的同层级,取历史层级压入
                    List<String> preLevelList = clazzStack.pop();
                    preLevelList.add(types.substring(startIndex, endIndex));
                    clazzStack.push(preLevelList);
                } else if (lastSymbol == '>') {
                    //不存在 > < 中间没有,情况
                    //clazzStack.push(init(types.substring(startIndex, endIndex)));
                    System.out.println("unknown case > xxx <");
                }
                startIndex = endIndex + 1;
                lastSymbol = '<';
            } else if (charAt == ',') {
                // ,同层级符号, 压入元素
                if (lastSymbol == '<'){
                    //,左侧为新层级的第一个元素(,表示必定有多个元素),新建层并压入
                    clazzStack.push(init(types.substring(startIndex, endIndex)));
                } else if (lastSymbol == ',') {
                    //,左侧为历史同层级的第N个元素,取历史层级压入
                    List<String> preLevelList = clazzStack.pop();
                    preLevelList.add(types.substring(startIndex, endIndex));
                    clazzStack.push(preLevelList);
                } else if (lastSymbol == '>') {
                    // >, 必然连在一起, 直接跳过这个,开始下标修改即可
                }
                startIndex = endIndex + 1;
                lastSymbol = ',';
            } else if (charAt == '>') {
                // > 结束符号, 进行业务逻辑处理
                if (lastSymbol == '<'){
                    // <>表示当前层级仅一个元素
                    //业务处理, 当前层仅一个元素
                    String curLevelSingleName = '<' + types.substring(startIndex, endIndex) + '>';
                    List<String> preLevelList = clazzStack.pop();
                    //业务处理, 加入到父元素
                    String lastClassName = preLevelList.get(preLevelList.size() - 1) + curLevelSingleName;
                    preLevelList.remove(preLevelList.size() - 1);
                    preLevelList.add(lastClassName);
                    clazzStack.push(preLevelList);
                } else if (lastSymbol == ',') {
                    // ,>表示当前层级有多个元素并结束,获取当前层最后一个元素后,拼接后加到前父元素
                    String preName = types.substring(startIndex, endIndex);
                    List<String> preLevelList = clazzStack.pop();
                    preLevelList.add(preName);
                    //业务处理, 整个层级拼接
                    String preNameList = '<' + StringUtils.join(preLevelList,",") + '>';
                    //业务处理, 再向上交给这层父节点处理
                    List<String> pre2LevelList = clazzStack.pop();
                    String lastClassName = pre2LevelList.get(pre2LevelList.size() - 1) + preNameList;
                    pre2LevelList.remove(pre2LevelList.size() - 1);
                    pre2LevelList.add(lastClassName);
                    clazzStack.push(pre2LevelList);
                } else if (lastSymbol == '>') {
                    // >>表示当前层无元素,且上一层级结束(>>必然连接在一起, 不需要向前截取)
                    List<String> preLevelList = clazzStack.pop();
                    //业务处理, 整个层级拼接
                    String preNameList = '<' + StringUtils.join(preLevelList,",") + '>';
                    //业务处理, 再向上交给这层父节点处理
                    List<String> pre2LevelList = clazzStack.pop();
                    String lastClassName = pre2LevelList.get(pre2LevelList.size() - 1) + preNameList;
                    pre2LevelList.remove(pre2LevelList.size() - 1);
                    pre2LevelList.add(lastClassName);
                    clazzStack.push(pre2LevelList);
                }
                startIndex = endIndex + 1;
                lastSymbol = '>';
            }

        }
        System.out.println(clazzStack.pop().get(0));
        System.out.println(types);

    }

    public static ParameterizedTypeImpl getTypes3(String types) throws Exception {

        //截取类型的开始下标
        int startIndex = 0;
        //截取类型的结束下标
        int endIndex;
        //上一次遇到的操作符号
        char lastSymbol = '<';

        Stack<List<TypeNode>> clazzStack = new Stack<>();
        if (!types.contains("<")){
            clazzStack.push(initNode(types));
        }

        types = types.replaceAll("\\s+", "");
        for (int i = 0; i < types.length(); i++) {
            endIndex = i;
            char charAt = types.charAt(i);
            // 注意: 每一次处理的是操作符号左边的数据
            if (charAt == '<') {
                // <开始符号, 压入元素
                if (lastSymbol == '<'){
                    //<左侧为新层级且仅有一个元素,新建层并压入
                    clazzStack.push(initNode(types.substring(startIndex, endIndex)));
                } else if (lastSymbol == ',') {
                    //<左侧为,的同层级,取历史层级压入
                    List<TypeNode> preLevelList = clazzStack.pop();
                    preLevelList.add(new TypeNode(types.substring(startIndex, endIndex)));
                    clazzStack.push(preLevelList);
                } else if (lastSymbol == '>') {
                    //不存在 > < 中间没有,情况
                    //clazzStack.push(init(types.substring(startIndex, endIndex)));
                    System.out.println("unknown case > xxx <");
                }
                startIndex = endIndex + 1;
                lastSymbol = '<';
            } else if (charAt == ',') {
                // ,同层级符号, 压入元素
                if (lastSymbol == '<'){
                    //,左侧为新层级的第一个元素(,表示必定有多个元素),新建层并压入
                    clazzStack.push(initNode(types.substring(startIndex, endIndex)));
                } else if (lastSymbol == ',') {
                    //,左侧为历史同层级的第N个元素,取历史层级压入
                    List<TypeNode> preLevelList = clazzStack.pop();
                    preLevelList.add(new TypeNode(types.substring(startIndex, endIndex)));
                    clazzStack.push(preLevelList);
                } else if (lastSymbol == '>') {
                    // >, 必然连在一起, 直接跳过这个,开始下标修改即可
                }
                startIndex = endIndex + 1;
                lastSymbol = ',';
            } else if (charAt == '>') {
                // > 结束符号, 进行业务逻辑处理
                if (lastSymbol == '<'){
                    // <>表示当前层级仅一个元素
                    List<TypeNode> curLevelList = initNode(types.substring(startIndex, endIndex));

                    //业务处理, 当前层与上1层拼接
                    dealCurAndPreNode(clazzStack, curLevelList);
                }else if (lastSymbol == ',') {
                    // ,>表示当前层级有多个元素并结束,获取当前层最后一个元素后,拼接后加到前父元素
                    String preName = types.substring(startIndex, endIndex);
                    List<TypeNode> preLevelList = clazzStack.pop();
                    preLevelList.add(new TypeNode(preName));

                    //业务处理, 上1层与上2层拼接
                    dealCurAndPreNode(clazzStack, preLevelList);
                }else if (lastSymbol == '>') {
                    // >>表示当前层无元素,且上一层级结束(>>必然连接在一起, 不需要向前截取)
                    List<TypeNode> preLevelList = clazzStack.pop();

                    //业务处理, 上1层与上2层拼接
                    dealCurAndPreNode(clazzStack, preLevelList);
                }
                startIndex = endIndex + 1;
                lastSymbol = '>';
            }

        }
        return clazzStack.pop().get(0).type;
    }

    public static void dealCurAndPreNode(Stack<List<TypeNode>> clazzStack, List<TypeNode> curLevelList) throws ClassNotFoundException {
        //业务处理, 当前层仅一个元素
        List<Type> clazzList = curLevelList.stream().map(node -> {
            try {
                if (null != node.type) {
                    return node.type;
                }
                return Class.forName(node.name);
            } catch (ClassNotFoundException e) {
                log.error("类找不到,配置异常,clazz:{}", node.name, e);
            }
            return null;
        }).collect(Collectors.toList());

        //业务处理, 加入到父元素
        List<TypeNode> preLevelList = clazzStack.pop();
        TypeNode pre2Node = preLevelList.get(preLevelList.size() - 1);
        pre2Node.type = new ParameterizedTypeImpl(clazzList.toArray(new Type[]{}), null, Class.forName(pre2Node.name));
        clazzStack.push(preLevelList);
    }

    static class TypeNode {
        public String name;
        public ParameterizedTypeImpl type;

        public TypeNode() {
        }

        public TypeNode(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "TypeNode{" +
                    "name='" + name + '\'' +
                    ", type=" + type +
                    '}';
        }
    }

    public static LinkedList<TypeNode> initNode(String className) {
        LinkedList<TypeNode> levelList = new LinkedList<>();
        levelList.add(new TypeNode(className));
        return levelList;
    }

}
基于 NSFW Model 色情图片识别鉴黄 后面更新视频检测 项目背景: 随着互联网的快速发展,网络上的信息量呈现出爆炸式的增长。然而,互联网上的内容良莠不齐,其中不乏一些不良信息,如色情、暴力等。这些信息对青少年的健康成长和社会风气产生了不良影响。为了净化网络环境,保护青少年免受不良信息的侵害,我国政府加大了对网络内容的监管力度。在此背景下,本项目应运而生,旨在实现对网络图片和视频的自动识别与过滤,助力构建清朗的网络空间。 项目简介: 本项目基于 NSFW(Not Safe For Work)Model,利用深度学习技术对色情图片进行识别与鉴黄。NSFW Model 是一种基于卷积神经网络(CNN)的图像识别模型,通过学习大量的色情图片和非色情图片,能够准确地判断一张图片是否含有色情内容。本项目在 NSFW Model 的基础上,进一步优化了模型结构,提高了识别的准确率和效率。 项目功能: 色情图片识别:用户上传图片后,系统会自动调用 NSFW Model 对图片进行识别,判断图片是否含有色情内容。如果含有色情内容,系统会给出相应的提示,并阻止图片的传播。 视频检测:针对网络视频,本项目采用帧提取技术,将视频分解为一帧帧图片,然后使用 NSFW Model 对这些图片进行识别。如果检测到含有色情内容的图片,系统会给出相应的提示,并阻止视频的传播。 实时监控:本项目可应用于网络直播、短视频平台等场景,实时监控画面内容,一旦检测到含有色情内容的画面,立即进行屏蔽处理,确保网络环境的纯洁。
### 如何在本地部署 NSFW 模型或服务 要在本地环境中成功部署 NSFW(不适宜工作场合内容)检测模型或服务,以下是详细的说明: #### 准备环境 为了确保能够顺利运行模型和服务,需要安装必要的依赖项。这些工具和库包括但不限于以下几类: - **Python 环境**: 推荐使用 Python 3.7 或更高版本。 - **Transformers 库**: 提供加载预训练模型的功能[^1]。 - **PyTorch/TensorFlow**: 支持深度学习框架的计算需求。 - **Pillow (PIL)**: 处理图像文件并将其转换为适合输入模型的形式。 具体命令如下所示: ```bash pip install transformers torch Pillow ``` #### 加载模型与测试 通过 Hugging Face 的 `transformers` 工具包可以直接访问已有的 NSFW 图片分类模型。例如,可以采用名为 `"Falconsai/nsfw_image_detection"` 的公开模型来完成此任务[^1]。 下面是一个简单的代码片段展示如何加载该模型并对单张图片执行预测操作: ```python from PIL import Image from transformers import pipeline def classify_nsfw(image_path): # 打开指定路径下的图片文件 img = Image.open(image_path) # 初始化 image-classification 流水线对象,并指明使用的特定模型名称 classifier = pipeline("image-classification", model="Falconsai/nsfw_image_detection") # 对传入的图片调用流水线方法得到其类别标签及其置信度分数列表形式的结果 result = classifier(img) return result if __name__ == "__main__": test_img_path = "<your_test_image>" output_results = classify_nsfw(test_img_path) print(output_results) ``` 注意替换 `<your_test_image>` 成实际存在的图片绝对或者相对地址字符串值之前再尝试运行以上脚本。 #### 构建 RESTful API 服务 如果希望进一步扩展功能至 Web 应用程序层面,则可考虑利用 Flask/Django 这样的轻量级 web 开发框架构建起支持 HTTP 请求交互的服务端接口。这里给出基于 FastAPI 实现的一个简单例子作为示范用途: ```python import uvicorn from fastapi import FastAPI, File, UploadFile from PIL import Image from io import BytesIO from typing import List from pydantic import BaseModel app = FastAPI() class Prediction(BaseModel): label: str score: float @app.post("/predict/", response_model=List[Prediction]) async def predict(file: UploadFile = File(...)): try: contents = await file.read() pil_image = Image.open(BytesIO(contents)) clf_pipeline = pipeline('image-classification', model='Falconsai/nsfw_image_detection') predictions = clf_pipeline(pil_image) formatted_preds = [{"label": pred['label'], "score": round(pred['score'], 4)} for pred in predictions] return formatted_preds except Exception as e: raise ValueError(f"Error processing uploaded file {e}") if __name__ == '__main__': uvicorn.run(app, host='0.0.0.0', port=8000) ``` 启动服务器之后即可向 `/predict/` 路径发送 POST 请求附带上传待分析的目标图片获取返回结果了。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值