package com.bfkj.unidia.DataUtils; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParserFactory; import javax.xml.stream.*; import javax.xml.stream.events.*; import java.io.*; import java.util.*; /** * 高性能、线程安全的数据格式转换工具类 * 支持: * - XML转Map(流式处理) * - 字符串转Map(自动识别JSON/XML) * - Map转JSON/XML(支持命名空间、CDATA) * - 流式处理,适用于海量数据场景 */ @Component public class DataFormatConverter { private static final Logger logger = LoggerFactory.getLogger(DataFormatConverter.class); private static final ObjectMapper objectMapper = new ObjectMapper(); private static final ThreadLocal xmlInputFactory = ThreadLocal.withInitial(() -> { XMLInputFactory factory = XMLInputFactory.newInstance(); try { factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false); factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); } catch (Exception e) { logger.warn("XMLInputFactory 创建失败", e); return null; } return factory; }); private static final ThreadLocal xmlOutputFactory = ThreadLocal.withInitial(() -> { XMLOutputFactory factory = XMLOutputFactory.newInstance(); try { factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true); } catch (Exception e) { logger.warn("XMLOutputFactory 初始化失败", e); return null; } return factory; }); private static final ThreadLocal saxParserFactory = ThreadLocal.withInitial(() -> { SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setNamespaceAware(true); return factory; }); static { objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); } // ===== XML 转 Map(流式处理) ===== public static Map xmlToMap(String xml) throws XMLStreamException { try (StringReader reader = new StringReader(xml)) { return xmlToMap(reader); }catch (XMLStreamException e){ logger.error("XML 转 Map 失败", e); return null; } } public static Map xmlToMap(Reader reader) throws XMLStreamException { XMLEventReader eventReader = xmlInputFactory.get().createXMLEventReader(reader); try { return parse(eventReader); }catch (XMLStreamException e){ logger.error("XML 转 Map 失败", e); return null; }finally { eventReader.close(); } } public static Map streamToMap(InputStream inputStream) throws XMLStreamException { XMLStreamReader xmlReader = xmlInputFactory.get().createXMLStreamReader(inputStream); XMLEventReader eventReader = null; try { eventReader = xmlInputFactory.get().createXMLEventReader(xmlReader); return parse(eventReader); } catch (XMLStreamException e) { logger.error("XML 转 Map 失败", e); return null; }finally { if (eventReader != null) { eventReader.close(); } xmlReader.close(); } } private static Map parse(XMLEventReader eventReader) throws XMLStreamException { Map result = new HashMap<>(); Deque path = new ArrayDeque<>(); Deque> mapStack = new ArrayDeque<>(); StringBuffer buffer = new StringBuffer(); while (eventReader.hasNext()) { if (buffer==null) buffer = new StringBuffer(); XMLEvent event = eventReader.nextEvent(); if (event.isStartElement()) { StartElement startElement = event.asStartElement(); String qualifiedName = startElement.getName().getLocalPart(); // 命名空间处理(略) path.push(qualifiedName); mapStack.push(new HashMap<>()); // 属性处理 Iterator attributes = startElement.getAttributes(); while (attributes.hasNext()) { Attribute attr = attributes.next(); String attrQName = attr.getName().getLocalPart(); if (mapStack.isEmpty()) { logger.error("无效XML结构:属性未关联到元素"); continue; } mapStack.peek().put("@" + attrQName, attr.getValue()); } } else if (event.isCharacters()) { Characters characters = event.asCharacters(); if (!characters.isWhiteSpace()) { String text = characters.getData(); if (text.equals(".J/G/PEKPORT//30JUN/205440L///XI/CL")){ System.out.println(text); } if (!mapStack.isEmpty() && mapStack.peek() != null) { if (characters.isCData()) { mapStack.peek().put("#cdata", text); } else { buffer.append(text); mapStack.peek().put("#text", buffer.toString()); } } } } else if (event.isEndElement()) { if (buffer!=null){ System.out.println("------------------------------buffer"); System.out.println(buffer.toString()); } buffer = null; if (!mapStack.isEmpty()) { Map current = mapStack.pop(); String key = path.pop(); mergeMap(result, key, current); } } } return result; } // ===== Map 转 XML ===== public static String mapToXml(Map map) { return mapToXml(map, "UTF-8", "1.0"); } /** * 集合xml批量转json字符串 * @param content * @return * @throws XMLStreamException */ public static List xmlsToMap(List content) throws XMLStreamException { List maps = new ArrayList<>(); if (content!=null&&content.size()>0){ for (String str : content) { System.out.println("接收到需要转换Map的数据"); Map map = xmlToMap(str); String jsonStr = mapToJson(map); maps.add(jsonStr); } } return maps; } public static String mapToXml(Map map, String encoding, String version) { StringWriter writer = new StringWriter(); try { XMLStreamWriter xmlWriter = xmlOutputFactory.get().createXMLStreamWriter(writer); try { xmlWriter.writeStartDocument(encoding, version); writeXml(map, xmlWriter); xmlWriter.writeEndDocument(); } finally { xmlWriter.close(); } } catch (XMLStreamException e) { throw new RuntimeException("Map转XML失败", e); } return writer.toString(); } private static void writeXml(Map map, XMLStreamWriter writer) throws XMLStreamException { for (Map.Entry entry : map.entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); if (value instanceof Map) { writer.writeStartElement(key); writeXml((Map) value, writer); writer.writeEndElement(); } else if (value instanceof List) { for (Object item : (List) value) { writer.writeStartElement(key); if (item instanceof Map) { writeXml((Map) item, writer); } else { writer.writeCData(item.toString()); // 写入 CDATA } writer.writeEndElement(); } } else if (key.startsWith("@")) { String attrName = key.substring(1); writer.writeAttribute(attrName, value.toString()); } else if ("#text".equals(key)) { writer.writeCharacters(value.toString()); } else if ("#cdata".equals(key)) { writer.writeCData(value.toString()); } else if (value != null) { writer.writeStartElement(key); writer.writeCharacters(value.toString()); writer.writeEndElement(); } } } // ===== 工具方法 ===== private static void mergeMap(Map target, String key, Map value) { if (target.containsKey(key)) { Object existing = target.get(key); if (existing instanceof List) { ((List) existing).add(value); } else if (existing instanceof Map) { List list = new ArrayList<>(); list.add(existing); list.add(value); target.put(key, list); } } else { target.put(key, value); } } // ===== 自动识别格式 ===== public static Map stringToMap(String input) { if (input == null || input.trim().isEmpty()) { throw new IllegalArgumentException("输入不能为空"); } char firstChar = input.trim().charAt(0); if (firstChar == '{' || firstChar == '[') { try { return objectMapper.readValue(input, Map.class); } catch (JsonProcessingException e) { logger.error("input输入参数:{}",input); throw new RuntimeException("JSON解析失败", e); } } else if (firstChar == '<') { try { return xmlToMap(input); } catch (XMLStreamException e) { throw new RuntimeException("XML解析失败", e); } } else { throw new IllegalArgumentException("不支持的输入格式"); } } public static String mapToJson(Map map) { try { return objectMapper.writeValueAsString(map); } catch (JsonProcessingException e) { throw new RuntimeException("Map转JSON失败", e); } } // ===== SAX 解析器回退 ===== public static Map saxXmlToMap(String xml) throws ParserConfigurationException, SAXException, IOException { SAXParserFactory factory = saxParserFactory.get(); CustomHandler handler = new CustomHandler(); try (StringReader reader = new StringReader(xml)) { factory.newSAXParser().parse(new InputSource(reader), handler); } return handler.getRoot(); } private static class CustomHandler extends DefaultHandler { private final Deque elementStack = new ArrayDeque<>(); private final Map root = new HashMap<>(); @Override public void startElement(String uri, String localName, String qName, Attributes attributes) { String key = qName; elementStack.push(key); Map attrs = new HashMap<>(); for (int i = 0; i < attributes.getLength(); i++) { String attrQName = attributes.getQName(i); String attrValue = attributes.getValue(i); attrs.put("@" + attrQName, attrValue); } if (!attrs.isEmpty()) { root.put("@" + key, attrs); } } @Override public void characters(char[] ch, int start, int length) { String text = new String(ch, start, length).trim(); if (!text.isEmpty() && !elementStack.isEmpty()) { root.put("#text", text); } } @Override public void endElement(String uri, String localName, String qName) { elementStack.pop(); } public Map getRoot() { return root; } } /** * 将对象转换为字符串(支持Map/List自动转JSON,其他类型返回toString) * 特性: * 1. 支持Map/List递归转换为JSON字符串 * 2. 完全禁用JSON转义符生成(含ASCII控制字符) * 3. 支持任意对象转换(非容器类型直接调用toString) * 4. 处理null值安全 */ public static String convertObjectToString(Object obj) { if (obj == null) { return null; } try { if(obj instanceof String strObj){ return strObj; } // 使用禁用转义的ObjectMapper实例 return NoEscapeObjectMapperHolder.INSTANCE.writeValueAsString(obj); } catch (JsonProcessingException e) { if (obj.getClass().isArray()) { // 处理数组类型 return Arrays.deepToString(new Object[]{obj}).substring(1, Arrays.deepToString(new Object[]{obj}).length()-1); } return obj.toString(); } } private static class NoEscapeObjectMapperHolder { // 使用构建器创建带特性的工厂实例 private static final ObjectMapper INSTANCE = new ObjectMapper( JsonFactory.builder() // .enable(JsonWriteFeature.QUOTE_CHARACTERS) // 启用无引号特性 .build() ); static { INSTANCE.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); INSTANCE.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); // 保留原有配置 INSTANCE.getFactory().configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, false); } } public static Map ObjectToMap(Object obj) { if(obj instanceof Map){ return (Map) obj; } return stringToMap((String) obj); } }