123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- 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> 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> 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> 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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> parse(XMLEventReader eventReader) throws XMLStreamException {
- Map<String, Object> result = new HashMap<>();
- Deque<String> path = new ArrayDeque<>();
- Deque<Map<String, Object>> 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<Attribute> 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<String, Object> current = mapStack.pop();
- String key = path.pop();
- mergeMap(result, key, current);
- }
- }
- }
- return result;
- }
- // ===== Map 转 XML =====
- public static String mapToXml(Map<String, Object> map) {
- return mapToXml(map, "UTF-8", "1.0");
- }
- /**
- * 集合xml批量转json字符串
- * @param content
- * @return
- * @throws XMLStreamException
- */
- public static List<String> xmlsToMap(List<String> content) throws XMLStreamException {
- List<String> maps = new ArrayList<>();
- if (content!=null&&content.size()>0){
- for (String str : content) {
- System.out.println("接收到需要转换Map的数据");
- Map<String, Object> map = xmlToMap(str);
- String jsonStr = mapToJson(map);
- maps.add(jsonStr);
- }
- }
- return maps;
- }
- public static String mapToXml(Map<String, Object> 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<String, Object> map, XMLStreamWriter writer) throws XMLStreamException {
- for (Map.Entry<String, Object> entry : map.entrySet()) {
- String key = entry.getKey();
- Object value = entry.getValue();
- if (value instanceof Map) {
- writer.writeStartElement(key);
- writeXml((Map<String, Object>) value, writer);
- writer.writeEndElement();
- } else if (value instanceof List) {
- for (Object item : (List<?>) value) {
- writer.writeStartElement(key);
- if (item instanceof Map) {
- writeXml((Map<String, Object>) 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<String, Object> target, String key, Map<String, Object> value) {
- if (target.containsKey(key)) {
- Object existing = target.get(key);
- if (existing instanceof List) {
- ((List<Object>) existing).add(value);
- } else if (existing instanceof Map) {
- List<Object> list = new ArrayList<>();
- list.add(existing);
- list.add(value);
- target.put(key, list);
- }
- } else {
- target.put(key, value);
- }
- }
- // ===== 自动识别格式 =====
- public static Map<String, Object> 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<String, Object> 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<String> elementStack = new ArrayDeque<>();
- private final Map<String, Object> root = new HashMap<>();
- @Override
- public void startElement(String uri, String localName, String qName, Attributes attributes) {
- String key = qName;
- elementStack.push(key);
- Map<String, Object> 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<String, Object> 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<String, Object> ObjectToMap(Object obj) {
- if(obj instanceof Map<?,?>){
- return (Map<String, Object>) obj;
- }
- return stringToMap((String) obj);
- }
- }
|