需求: 如何动态的获取一个对象的字段,假如一个对象里面有name,age,sex三个字段,我想取name的值,这个name是存在一个json中,json的格式如下[{"key":"name"},{"key":"age"},{"key":"sex"}]先遍历这个json,然后再根据key的值,取对象中对应的属性值。 也就是获取json对应的key的value,封装到对象中。
GPT给出的答案:
- 在 Java 中,你可以按照以下步骤动态获取一个对象的字段:
-
- 1. 遍历 JSON 数组,获取每个对象的 `key` 值。
- 2. 使用获取到的 `key` 值作为属性名称,利用 Java 反射机制获取对象的对应属性值。
-
- 下面是一个示例代码:
-
-
- import com.fasterxml.jackson.databind.JsonNode;
- import com.fasterxml.jackson.databind.ObjectMapper;
-
- import java.util.List;
-
- public class Main {
- public static void main(String[] args) throws Exception {
- String jsonStr = "[{\"key\":\"name\"},{\"key\":\"age\"},{\"key\":\"sex\"}]";
-
- ObjectMapper objectMapper = new ObjectMapper();
- List
data = objectMapper.readValue(jsonStr, List.class); -
- Person person = new Person("John", 25, "male");
-
- for (JsonNode item : data) {
- String key = item.get("key").asText();
- Object value = getValueByKey(person, key);
- System.out.println(key + ": " + value);
- }
- }
-
- public static Object getValueByKey(Object obj, String key) throws Exception {
- return obj.getClass().getMethod("get" + capitalize(key)).invoke(obj);
- }
-
- public static String capitalize(String str) {
- if (str == null || str.isEmpty()) {
- return str;
- }
- return Character.toUpperCase(str.charAt(0)) + str.substring(1);
- }
- }
-
- class Person {
- private String name;
- private int age;
- private String sex;
-
- public Person(String name, int age, String sex) {
- this.name = name;
- this.age = age;
- this.sex = sex;
- }
-
- public String getName() {
- return name;
- }
-
- public int getAge() {
- return age;
- }
-
- public String getSex() {
- return sex;
- }
- }
-
-
- 这段代码将输出:
-
-
- name: John
- age: 25
- sex: male
-
-
- 请注意,上述代码中的 `Person` 类是一个简单的示例,具有 `name`、`age` 和 `sex` 三个字段,并为每个字段提供了对应的 `get` 方法。你可以根据你的实际需求修改代码以适应你的对象结构和命名规则。
-
问题: 基于上面的问题,那要是想设置对象属性值呢?
GPT的答案:
- 如果你想设置对象的属性值,你可以按照以下步骤进行操作:
-
- 1. 遍历 JSON 数组,获取每个对象的 `key` 值和对应的属性值。
- 2. 使用获取到的 `key` 值作为属性名称,利用 Java 反射机制设置对象的属性值。
-
- 下面是一个示例代码:
-
-
- import com.fasterxml.jackson.databind.JsonNode;
- import com.fasterxml.jackson.databind.ObjectMapper;
-
- import java.util.List;
-
- public class Main {
- public static void main(String[] args) throws Exception {
- String jsonStr = "[{\"key\":\"name\",\"value\":\"John\"},{\"key\":\"age\",\"value\":25},{\"key\":\"sex\",\"value\":\"male\"}]";
-
- ObjectMapper objectMapper = new ObjectMapper();
- List
data = objectMapper.readValue(jsonStr, List.class); -
- Person person = new Person();
-
- for (JsonNode item : data) {
- String key = item.get("key").asText();
- Object value = item.get("value").asText();
- setValueByKey(person, key, value);
- }
-
- System.out.println(person);
- }
-
- public static void setValueByKey(Object obj, String key, Object value) throws Exception {
- obj.getClass().getMethod("set" + capitalize(key), value.getClass()).invoke(obj, value);
- }
-
- public static String capitalize(String str) {
- if (str == null || str.isEmpty()) {
- return str;
- }
- return Character.toUpperCase(str.charAt(0)) + str.substring(1);
- }
- }
-
- class Person {
- private String name;
- private int age;
- private String sex;
-
- public Person() {
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
-
- public String getSex() {
- return sex;
- }
-
- public void setSex(String sex) {
- this.sex = sex;
- }
-
- @Override
- public String toString() {
- return "Person{" +
- "name='" + name + '\'' +
- ", age=" + age +
- ", sex='" + sex + '\'' +
- '}';
- }
- }
-
-
- 这段代码将输出:
-
- Person{name='John', age=25, sex='male'}
-
-
- 请注意,上述代码中的 `Person` 类是一个简单的示例,具有 `name`、`age` 和 `sex` 三个字段,并为每个字段提供了对应的 `get` 和 `set` 方法。你可以根据你的实际需求修改代码以适应你的对象结构和命名规则。
-
具体在工作中的处理逻辑:
- 1. Mysql 任务属性字段已经确认,例如字段已经有了name,age
- 2. 变更:属性字段可配置,即支持用户前端设置,例如用户需要添加属性 地址address,联系方式phone等字段,字段个数不定。同时支持可以设置默认值或者选项值,例如:性别:男、女
- 3. 要求:在不修改Mysql结构的情况下,支持变更要求
- 4. 解决:① 设计规则,形成json规则字符串。
- 在创建任务的时候记录 此时用户需要的字段,若是已经存在的字段-则直接记录。 若是新添加的属性,则直接记录。
- ② 设置Mysql对应结果字段,原有字段不变,例如:name,age。动态字段可以在表中新增一个custom_field,数据是json形式的,例如[{"key":"我的自定义标签","value":"val2"}]保存动态字段结果。
- 交互如下:
- ③ 结果返回前端展示:查询数据库,将对象转换JSON,返回前端。JSON具体格式前后端商量即可。
- ④ 前端提交参数入库(编辑):JSON转换对象,操作数据库保存。
- 5. 技术:JSON和反射
-
-
- [
- {
- "canUpdate": 1,
- "enable": 1,
- "fieldName": "affiliatedCompany", //对应mysql表字段affiliated_company
- "id": 11,
- "inputBox": 1,
- "insertTime": "2023-09-05 15:45:02",
- "remark": "",
- "sort": 10,
- "status": 1,
- "tag": "所属公司", //字段的中文含义,在页面显示
- "type": 1,
- "updateTime": "2023-09-14 17:55:04"
- },
- {
- "canUpdate": 1,
- "enable": 1,
- "fieldName": "url", //对应mysql表字段url
- "id": 64,
- "inputBox": 1,
- "insertTime": "2023-10-09 09:42:19",
- "remark": "",
- "status": 1,
- "tag": "网址",
- "type": 1,
- "updateTime": "2023-10-09 11:14:34"
- },
- {
- "canUpdate": 1,
- "dicInfoList": [
- {
- "dicValue": "val1",
- "id": 104,
- "tagLibraryId": 68
- },
- {
- "dicValue": "val2",
- "id": 105,
- "tagLibraryId": 68
- },
- {
- "dicValue": "val3",
- "id": 106,
- "tagLibraryId": 68
- }
- ], //下拉框的可选项
- "enable": 1,
- "fieldName": "", //自定义添加的,没有mysql对应字段,这个值就是空字符串
- "id": 68,
- "inputBox": 2,
- "insertTime": "2024-01-28 14:21:24",
- "remark": "",
- "status": 1,
- "tag": "我的自定义标签", //自定义添加的,页面显示
- "type": 1,
- "updateTime": "2024-01-28 14:21:24"
- }
- ]
-
-
- 相关代码Util
-
- /**
- * @description: 将 对象中的属性值 ,转换json
- * @return: void
- * @author: hezha
- * @time: 2023/9/12 16:19
- */
- public static void transData(net.sf.json.JSONArray jsonArray, Object obj) {
- try {
- for(int i=0; i< jsonArray.size() ;i++){
- net.sf.json.JSONObject jsonObject = jsonArray.getJSONObject(i);
- String key = jsonObject.getString("key");
- String field = jsonObject.getString("field");
- if(org.apache.commons.lang3.StringUtils.isNotEmpty(field)){
- //有值,代表是基础指标,数据库就会存在对应的字段
- Object value = getValueByKey(obj, field);
- jsonObject.put("value", value!=null?value:"");
- }else{
- //无值,就是这个json不是基础字段,是扩展字段,就是存储在custom_field中的
- Object customField = getValueByKey(obj, "customField");
- if(customField != null){
- String customFieldStr = (String) customField;
- JSONArray customFieldArr = JSONArray.fromObject(customFieldStr);
- for(int j= 0; j< customFieldArr.size(); j++){
- JSONObject customFieldJson = customFieldArr.getJSONObject(j);
- String customFieldKey = customFieldJson.getString("key");
- String customFieldValue = customFieldJson.getString("value");
- if(key.equals(customFieldKey)){
- jsonObject.put("value", customFieldValue);
- }
- }
- }
- }
- }
- }catch (Exception e){
- e.printStackTrace();
- }
-
- }
-
-
- public static Object getValueByKey(Object obj, String key) throws Exception {
- return obj.getClass().getMethod("get" + capitalize(key)).invoke(obj);
- }
-
- public static String capitalize(String str) {
- if (str == null || str.isEmpty()) {
- return str;
- }
- return Character.toUpperCase(str.charAt(0)) + str.substring(1);
- }
-
-
- public static void setValueByKey(Object obj, String key, Object value) throws Exception {
- obj.getClass().getMethod("set" + capitalize(key), value.getClass()).invoke(obj, value);
- }
-
-
-
- /**
- * @description: 将json字符串转换对用的对象
- * @return: java.lang.Object
- * @author: hezha
- * @time: 2023/9/5 20:16
- */
- public static Object transObj(String jsonStr, Object obj){
- JSONArray array = new JSONArray();
- try {
- JSONArray jsonArray = JSONArray.fromObject(jsonStr);
- for(int i=0; i< jsonArray.size(); i++){
- JSONObject jsonObject = jsonArray.getJSONObject(i);
- String field = jsonObject.get("field") != null? jsonObject.getString("field"):"";
- Object value = jsonObject.get("value") != null? jsonObject.get("value"):"";
- if(com.wenge.util.StringUtils.isNotEmpty(field)){
- //字段不为空,就是基础字段,数据库中就有字段来保存
- Helper.setValueByKey(obj, field, value);
- }else{
- JSONObject json = new JSONObject();
- //如果是null 就是扩展字段,所有的扩展字段使用一个json 存储在custom_field中
- String key = jsonObject.getString("key");
- json.put("key", key);
- json.put("value", value);
- array.add(json);
- }
-
- }
-
- if(array.size() > 0){
- setValueByKey(obj, "CustomField", array.toString());
- }
- }catch (Exception e){
- e.printStackTrace();
- }
-
- return obj;
-
- }
-