001package gudusoft.gsqlparser.util.json; 002 003import gudusoft.gsqlparser.dlineage.util.BeanUtil; 004 005import java.io.Serializable; 006import java.lang.reflect.Array; 007import java.text.StringCharacterIterator; 008import java.util.LinkedHashMap; 009import java.util.List; 010import java.util.Map; 011 012@SuppressWarnings("rawtypes") 013public class JSONSerializer implements Serializable { 014 015 private static final long serialVersionUID = -947149613761603468L; 016 017 private boolean ignoreId = false; 018 019 public JSONSerializer(boolean ignoreId) { 020 this.ignoreId = ignoreId; 021 } 022 023 public JSONSerializer() { 024 } 025 026 private void check(Object obj) { 027 if (obj == null || !(obj instanceof LinkedHashMap || obj instanceof List)) { 028 throw new IllegalArgumentException("Invalid JSON structure"); 029 } 030 } 031 032 public String serialize(List list) { 033 check(list); 034 StringBuilder sb = new StringBuilder("["); 035 for (Object element : list) { 036 if (element == null) { 037 continue; // Skip null values 038 } 039 if (element instanceof List) 040 sb.append(serializeList((List) element)); 041 else if (element.getClass().isArray()) 042 sb.append(serializeArray(element)); 043 else if (element instanceof LinkedHashMap) 044 sb.append(serialize(BeanUtil.bean2Map(element))).append(","); 045 else 046 appendValue(sb, element); 047 } 048 String result = sb.toString(); 049 if (result.endsWith(",")) 050 result = result.substring(0, result.length() - 1); 051 return result + "]"; 052 } 053 054 public String serialize(Map map) { 055 check(map); 056 StringBuilder sb = new StringBuilder("{"); 057 for (Object k : map.keySet()) { 058 String key = (String) k; 059 if (ignoreId && ("id".equals(key))) { 060 continue; 061 } 062 Object val = map.get(key); 063 if (val == null) { 064 continue; // Skip null values 065 } 066 if (val instanceof List) 067 sb.append("\"").append(key).append("\":[").append(serializeList((List) val)).append("]").append(","); 068 else if (val.getClass().isArray()) 069 sb.append("\"").append(key).append("\":[").append(serializeArray(val)).append("]").append(","); 070 else if (val instanceof LinkedHashMap) 071 sb.append("\"").append(key).append("\":").append(serialize(BeanUtil.bean2Map(val))).append(","); 072 else 073 appendEntry(sb, key, val); 074 } 075 String result = sb.toString(); 076 if (result.endsWith(",")) 077 result = result.substring(0, result.length() - 1); 078 return result + "}"; 079 } 080 081 private String serializeList(List list) { 082 StringBuilder sb = new StringBuilder(); 083 int n = list.size(); 084 for (int i = 0; i < n; i++) { 085 Object obj = list.get(i); 086 if (obj == null) { 087 continue; // Skip null values 088 } 089 if (obj instanceof String) 090 sb.append("\"").append(escape((String) obj)).append("\""); 091 else 092 sb.append(serialize(BeanUtil.bean2Map(obj))); 093 if (i < n - 1) 094 sb.append(","); 095 } 096 return sb.toString(); 097 } 098 099 private String serializeArray(Object array) { 100 int n = Array.getLength(array); 101 StringBuilder sb = new StringBuilder(); 102 for (int i = 0; i < n; i++) { 103 Object obj = Array.get(array, i); 104 if (obj == null) { 105 continue; // Skip null values 106 } 107 if (obj instanceof String) 108 sb.append("\"").append(escape((String) obj)).append("\""); 109 else 110 sb.append(serialize(BeanUtil.bean2Map(obj))); 111 if (i < n - 1) 112 sb.append(","); 113 } 114 return sb.toString(); 115 } 116 117 private void appendEntry(StringBuilder sb, String key, Object val) { 118 boolean quote = false; 119 if (!(val instanceof String || val instanceof Number || val instanceof Boolean)) 120 val = serialize(BeanUtil.bean2Map(val)); 121 else if (val instanceof String) { 122 val = escape((String) val); 123 quote = true; 124 } 125 sb.append("\"").append(key).append("\":").append(quote ? "\"" : "").append(val).append(quote ? "\"" : "") 126 .append(","); 127 } 128 129 private void appendValue(StringBuilder sb, Object val) { 130 boolean quote = false; 131 if (!(val instanceof String || val instanceof Integer || val instanceof Long || val instanceof Boolean)) 132 val = serialize(BeanUtil.bean2Map(val)); 133 else if (val instanceof String) { 134 val = escape((String) val); 135 quote = true; 136 } 137 sb.append(quote ? "\"" : "").append(val).append(quote ? "\"" : "").append(","); 138 } 139 140 private static String escape(String str) { 141 StringBuilder sb = new StringBuilder(); 142 StringCharacterIterator it = new StringCharacterIterator(str); 143 char ch = it.current(); 144 while (ch != StringCharacterIterator.DONE) { 145 switch (ch) { 146 case '"': 147 sb.append("\\\""); 148 break; 149 case '\t': 150 sb.append("\\t"); 151 break; 152 case '\f': 153 sb.append("\\f"); 154 break; 155 case '\n': 156 sb.append("\\n"); 157 break; 158 case '\r': 159 sb.append("\\r"); 160 break; 161 case '\\': 162 sb.append("\\\\"); 163 break; 164 case '/': 165 sb.append("\\/"); 166 break; 167 case '\b': 168 sb.append("\\b"); 169 break; 170 default: 171 sb.append(ch); 172 } 173 ch = it.next(); 174 } 175 return sb.toString(); 176 } 177}