java原生方法实现url参数与map互转,x-www-form-urlencoded编码/解码实现,可实现复杂对象转换

最近在研究java原生方法实现http服务,但网上一直没有找到可靠的x-www-form-urlencoded编码/解码代码,要么找到的就是简单的一维key-value转换,无法实现复杂对象的转换,例如提交以下参数:
复杂对象提交后java如何转换为map?
我写的代码提供两个静态方法,分别是实现编码的方法public static String urlencode(Object params, String key),和实现解码的方法public static Map<String, Object> urldecode(String param)。
编码方法传入的params参数支持包含String、Number、Map、List或者上述类型的数组对象。
解码方法输出统一是map对象,如传入的参数包含有数组或者list对象,则输出时统一转化为list对象。

代码中已经提供了测试方法,运行main方法即可看到结果。
在这里插入图片描述

package com.util;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.ArrayUtils;

public class HttpUrlParams {
	
	public static void main(String args[]) {
		Map<String, Object> map = new HashMap<String, Object>();
			List<Object> list = new ArrayList<Object>();
			list.add("aa");
			list.add(123);
			list.add(new Object[] {"qq", 11});
		map.put("list", list);
			Map<String, Object> childMap = new HashMap<String, Object>();
			childMap.put("num", 78);
			childMap.put("str", "str?!+-str");
			childMap.put("array", new int[] {44,55});
		map.put("childMap", childMap);
		map.put("array", new String[] {"ss", "Kk"});
		
		System.out.println(map);
		String encodeStr = urlencode(map, "");
		System.out.println(encodeStr);
		Object decodeObj = urldecode(encodeStr);
		System.out.println(decodeObj);
	}
	
	public static String urlencode(Object params, String key) {
		String res = "";
		if(params instanceof Map) {
			Map<String, Object> _params = (Map<String, Object>) params;
			for(String i : _params.keySet()) {
				String k = key.isEmpty() ? i : (key +"["+ i +"]");
				String encodeValue = urlencode(_params.get(i), k);
				if(!encodeValue.isEmpty()) {
					res += '&'+ encodeValue;
				}
			}
		}
		else if(params instanceof List) {
			List<Object> _params = (List<Object>) params;
			for(Integer i = 0; i < _params.size(); i++) {
				String k = key.isEmpty() ? i.toString() : (key +"["+ i.toString() +"]");
				String encodeValue = urlencode(_params.get(i), k);
				if(!encodeValue.isEmpty()) {
					res += '&'+ encodeValue;
				}
			}
		}
		else if(params.getClass().isArray()) {
			Object[] _params;
			if(params instanceof Object[]) {
				_params = (Object[]) params;
			}
			else if(params instanceof String[]) {
				_params = (String[]) params;
			}
			else if(params instanceof int[]) {
				_params = ArrayUtils.toObject((int[]) params);
			}
			else if(params instanceof double[]) {
				_params = ArrayUtils.toObject((double[]) params);
			}
			else {
				_params = new Object[] {};
			}
			for(Integer i = 0; i < _params.length; i++) {
				String k = key.isEmpty() ? i.toString() : (key +"["+ i.toString() +"]");
				String encodeValue = urlencode(_params[i], k);
				if(!encodeValue.isEmpty()) {
					res += '&'+ encodeValue;
				}
			}
		}
		else if(params instanceof String) {
			String _params = (String) params;
			try {
				res += '&'+ URLEncoder.encode(key, "UTF-8") +'='+ URLEncoder.encode(_params, "UTF-8");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		else if(params instanceof Number) {
			Number _params = (Number) params;
			try {
				res += '&'+ URLEncoder.encode(key, "UTF-8") +'='+ URLEncoder.encode(_params.toString(), "UTF-8");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		else {
			return "";
		}
		return res.substring(1);
	}
	
	
	public static Map<String, Object> urldecode(String param) {
		if(param == null || param.isEmpty()) {
			return null;
		}
		//解码
		String[] params = param.split("&");
		Map<String, String> key2value = new TreeMap<String, String>();
		for(int i = 0; i < params.length; i++) {
			String[] p = params[i].split("=");
			if(p.length == 0) {
				continue;
			}
			try {
				String keyStr = URLDecoder.decode(p[0], "UTF-8");
				if(keyStr.isBlank()) {
					continue;
				}
				String valueStr;
				if(p.length == 2) {
					valueStr = URLDecoder.decode(p[1], "UTF-8");
				} else {
					valueStr = "";
				}
				key2value.put(keyStr, valueStr);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		//遍历每一行传参
		Map<String, Object> map = new HashMap<String, Object>();
		for(Map.Entry<String, String> entry : key2value.entrySet()) {
			String keyStr = entry.getKey();
			String value = entry.getValue();
			//根目录的key
			Matcher keyMatcher = Pattern.compile("^[a-zA-Z\\_]{1}[\\w]*").matcher(keyStr);
			if(!keyMatcher.find()) {
				continue;
			}
			String key = keyMatcher.group(0);
			if(!map.containsKey(key)) {
				map.put(key, new HashMap<String, Object>());
			}
			
			//二级以及二级目录以上的key
			String pattern = "\\[([\\w]+?)\\]";
			Matcher filterMatcher = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE).matcher(keyStr);
			//获取所有的patternKey
			List<String> patternKeyList = new ArrayList<String>();
			while(filterMatcher.find()) {
				String patternKey = filterMatcher.group(1);
				patternKeyList.add(patternKey);
			}
			//有子元素
			if(!patternKeyList.isEmpty()) {
				//遍历并写入
				Object childMap = map.get(key);
				int patternKeyListSize = patternKeyList.size();
				for(int j = 0; j < patternKeyListSize; j++) {
					String patternKey = patternKeyList.get(j);
					Map<String, Object> _childMap = (HashMap<String, Object>) childMap;
					if(!_childMap.containsKey(patternKey)) {
						//是否是最后一个节点,是的话直接赋值
						if(j == patternKeyListSize-1) {
							_childMap.put(patternKey, value);
							break;
						}
						_childMap.put(patternKey, new HashMap<String, Object>());
					}
					childMap = _childMap.get(patternKey);
				}
			}
			//只有一级元素
			else {
				map.put(key, value);
			}
		}
		map = (Map<String, Object>) map2list(map);
		return map;
	}
	
	private static Object map2list(Map<String, Object> map) {
		Set<String> keySet = map.keySet();
		boolean all_is_number = true;
		for(String key : keySet) {
			//不是数字
			if(!Pattern.matches("^[0-9]+$", key)) {
				all_is_number = false;
			}
			Object childNode = map.get(key);
			if(childNode instanceof Map) {
				childNode = map2list((Map<String, Object>) childNode);
				map.put(key, childNode);
			}
		}
		Object res;
		if(all_is_number) {
			res = new ArrayList<Object>();
			for(String key : keySet) {
				Object value = map.get(key);
				((List<Object>) res).add(value);
			}
		} else {
			res = map;
		}
		return res;
	}

}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JAVA中有一个标准库叫做`java.net.URLEncoder`,可以将普通字符串编码为`application/x-www-form-urlencoded`格式。同样地,也有一个标准库叫做`java.net.URLDecoder`,可以将`application/x-www-form-urlencoded`格式的字符串解码为普通字符串。 下面是一个将普通字符串编码为`application/x-www-form-urlencoded`格式的示例代码: ```java import java.net.URLEncoder; String plainText = "这是一段中文文本"; String encodedText = URLEncoder.encode(plainText, "UTF-8"); System.out.println(encodedText); // 输出:%E8%BF%99%E6%98%AF%E4%B8%80%E6%AE%B5%E4%B8%AD%E6%96%87%E6%96%87%E6%9C%AC ``` 在这个示例中,我们将一个包含中文文本的普通字符串`plainText`编码为`application/x-www-form-urlencoded`格式的字符串`encodedText`。`URLEncoder.encode`方法的第一个参数是要编码的字符串,第二个参数是使用的字符集,这里我们使用UTF-8字符集。 下面是一个将`application/x-www-form-urlencoded`格式的字符串解码为普通字符串的示例代码: ```java import java.net.URLDecoder; String encodedText = "%E8%BF%99%E6%98%AF%E4%B8%80%E6%AE%B5%E4%B8%AD%E6%96%87%E6%96%87%E6%9C%AC"; String plainText = URLDecoder.decode(encodedText, "UTF-8"); System.out.println(plainText); // 输出:这是一段中文文本 ``` 在这个示例中,我们将一个`application/x-www-form-urlencoded`格式的字符串`encodedText`解码为普通字符串`plainText`。`URLDecoder.decode`方法的第一个参数是要解码的字符串,第二个参数是使用的字符集,这里我们同样使用UTF-8字符集。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值