【我的Android进阶之旅】解决Jackson解析json字符串报错:no single-String constructor/factory method

版权声明:本文为【欧阳鹏】原创文章,欢迎转载,转载请注明出处! 【http://blog.csdn.net/ouyang_peng】 https://blog.csdn.net/qq446282412/article/details/82492314

一、问题描述

今天在使用Jackson解析json字符串的时候,报了如下所示的错误

09-07 09:08:11.013 13311-13418/com.xtc.data.demo E/com.xtc.bigdata.common.utils.JSONUtil: 
com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, 
class com.xtc.bigdata.collector.config.FilterInfoBean] from String value ('k'); no single-String 
constructor/factory method
     at [Source: [B@b8ddf88; line: 1, column: 1], 
     jsonStr:"k":"filter_key","isVisible":true,"description":"功能开关",
     "v":[{"functionName":"func_test1","packageName":"packageName1"},
     {"functionName":"func_test2","packageName":"packageName2"}]}, 
     classType:com.xtc.bigdata.collector.config.FilterInfoBean

这里写图片描述

二、分析问题

从什么的提示可以看出来,提示我们

no single-String constructor/factory method
没有 单个字符串构造/工厂方法

我们先来看看 修改之前的代码

  • FilterInfoBean.java
    上面解析使用的FilterInfoBean代码如下所示:
package com.xtc.bigdata.collector.config;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import java.util.List;

/**
 * 大数据的过滤信息封装实体类
 * </p>
 * created by OuyangPeng at 2018/9/6 下午 05:24
 * @author OuyangPeng
 */
@JsonIgnoreProperties(ignoreUnknown = true)
public class FilterInfoBean {
    private String k;
    private boolean isVisible;
    private String description;
    private List<FilterFunctionItem> v;

    public String getK() {
        return k;
    }

    public void setK(String k) {
        this.k = k;
    }

    public boolean isIsVisible() {
        return isVisible;
    }

    public void setIsVisible(boolean isVisible) {
        this.isVisible = isVisible;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public List<FilterFunctionItem> getV() {
        return v;
    }

    public void setV(List<FilterFunctionItem> v) {
        this.v = v;
    }

    @Override
    public String toString() {
        return "FilterInfoBean{" +
                "k='" + k + '\'' +
                ", isVisible=" + isVisible +
                ", description='" + description + '\'' +
                ", v=" + v +
                '}';
    }
}

这里写图片描述

  • FilterFunctionItem.java
    上面使用到的FilterFunctionItem,代码如下
package com.xtc.bigdata.collector.config;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public class FilterFunctionItem {
    /**
     * 需要过滤的functionName
     */
    private String functionName;
    /**
     * 需要过滤的packageName
     */
    private String packageName;

    public String getFunctionName() {
        return functionName;
    }

    public void setFunctionName(String functionName) {
        this.functionName = functionName;
    }

    public String getPackageName() {
        return packageName;
    }

    public void setPackageName(String packageName) {
        this.packageName = packageName;
    }

    @Override
    public String toString() {
        return "FilterFunctionItem{" +
                "functionName='" + functionName + '\'' +
                ", packageName='" + packageName + '\'' +
                '}';
    }
}
  • JSONUtil.java
    json使用的Jackson的封装Util类,代码如下:
package com.xtc.bigdata.common.utils;

import android.util.Log;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.xtc.log.LogUtil;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;

/**
 * JSON转换工具类
 */
public class JSONUtil {

    private static String TAG = JSONUtil.class.getName();

    private static ObjectMapper mapper = new ObjectMapper();

    static {
        //对于为null的字段不进行序列化
        mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
        //对于未知属性不进行反序列化
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
        mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
        //无论对象中的值只有不为null的才进行序列化
        mapper.setSerializationInclusion(Include.NON_NULL);
    }

    /**
     * 把对象转化成json字符串
     *
     * @param obj
     * @return
     */
    public static String toJSON(Object obj) {
        if (obj == null) {
            return null;
        }

        Writer write = new StringWriter();
        try {
            mapper.writeValue(write, obj);
        } catch (JsonGenerationException e) {
            Log.e(TAG, e.toString() + obj);
        } catch (JsonMappingException e) {
            Log.e(TAG, e.toString() + obj);
        } catch (IOException e) {
            Log.e(TAG, e.toString() + obj);
        }
        return write.toString();
    }

    /**
     * JSON字符串转成对象
     *
     * @param jsonStr
     * @param classType
     * @return
     */
    public static <T> T fromJSON(String jsonStr, Class<T> classType) {
        if (isEmptyOrNull(jsonStr)) {
            return null;
        }

        T t = null;
        try {
            t = mapper.readValue(jsonStr.getBytes("utf-8"), classType);
        } catch (JsonParseException e) {
            Log.e(TAG, e.toString() + ", jsonStr:" + jsonStr + ", classType:" + classType.getName());
        } catch (JsonMappingException e) {
            Log.e(TAG, e.toString() + ", jsonStr:" + jsonStr + ", classType:" + classType.getName());
        } catch (IOException e) {
            Log.e(TAG, e.toString() + ", jsonStr:" + jsonStr + ", classType:" + classType.getName());
        }
        return t;
    }

    /**
     * 判断字符串是否为null或者""
     */
    private static boolean isEmptyOrNull(String content) {
        return content == null || "".equals(content);
    }

    /**
     * JSON字符串转化成集合
     *
     * @param jsonStr
     * @return
     */
    public static <T> T toCollection(String jsonStr, Class<?> collectionClass, Class<?>... elementClasses) {
        if (isEmptyOrNull(jsonStr)) {
            return null;
        }

        T t = null;
        try {
            t = mapper.readValue(jsonStr.getBytes("utf-8")
                    , mapper.getTypeFactory().constructParametricType(collectionClass, elementClasses));
        } catch (JsonParseException e) {
            LogUtil.e(e);
            Log.e(TAG, e.toString() + ", jsonStr:" + jsonStr);
        } catch (JsonMappingException e) {
            LogUtil.e(e);
            Log.e(TAG, e.toString() + ", jsonStr:" + jsonStr);
        } catch (IOException e) {
            Log.e(TAG, e.toString() + ", jsonStr:" + jsonStr);
        }
        return t;
    }

    public static Object get(String jsonStr, String key) {
        Object obj = null;
        try {
            JSONObject jsonObj = new JSONObject(jsonStr);
            obj = jsonObj.get(key);
        } catch (JSONException e) {
            LogUtil.e(e);
        }
        return obj;
    }
}

三、添加单个字符串构造方法

将上面使用到的FilterInfoBean,添加一个单个字符串构造方法,如下所示

这里写图片描述

package com.xtc.bigdata.collector.config;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import java.util.List;

/**
 * 大数据的过滤信息封装实体类
 * </p>
 * created by OuyangPeng at 2018/9/6 下午 05:24
 * @author OuyangPeng
 */
@JsonIgnoreProperties(ignoreUnknown = true)
public class FilterInfoBean {
    private String k;
    private boolean isVisible;
    private String description;
    private List<FilterFunctionItem> v;

    public FilterInfoBean(String k){
        this.k = k;
    }

    public String getK() {
        return k;
    }

    public void setK(String k) {
        this.k = k;
    }

    public boolean isIsVisible() {
        return isVisible;
    }

    public void setIsVisible(boolean isVisible) {
        this.isVisible = isVisible;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public List<FilterFunctionItem> getV() {
        return v;
    }

    public void setV(List<FilterFunctionItem> v) {
        this.v = v;
    }

    @Override
    public String toString() {
        return "FilterInfoBean{" +
                "k='" + k + '\'' +
                ", isVisible=" + isVisible +
                ", description='" + description + '\'' +
                ", v=" + v +
                '}';
    }
}

然后重新运行程序,发现又有一个新的错误出现了,如下所示:

09-07 10:00:55.431 4721-4721/com.xtc.data.demo E/com.xtc.bigdata.common.utils.JSONUtil: 
com.fasterxml.jackson.databind.JsonMappingException: 
No suitable constructor found for type [simple type,
 class com.xtc.bigdata.collector.config.FilterInfoBean]: 
 can not instantiate from JSON object (missing default constructor or creator, 
 or perhaps need to add/enable type information?)
     at [Source: [B@e1fe848; line: 1, column: 2], jsonStr:
     {"k":"filter_key","isVisible":true,"description":"功能开关",
     "v":[{"functionName":"func_test1","packageName":"packageName1"},
     {"functionName":"func_test2","packageName":"packageName2"}]}, 
     classType:com.xtc.bigdata.collector.config.FilterInfoBean

这里写图片描述

好家伙,居然提示我

can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)

不能从JSON对象实例化(缺少默认构造函数或创建者,或者可能需要添加/启用类型信息)

好吧,就按照你的提示,再加一个默认的构造方法,如下所示

这里写图片描述

package com.xtc.bigdata.collector.config;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import java.util.List;

/**
 * 大数据的过滤信息封装实体类
 * </p>
 * created by OuyangPeng at 2018/9/6 下午 05:24
 * @author OuyangPeng
 */
@JsonIgnoreProperties(ignoreUnknown = true)
public class FilterInfoBean {
    private String k;
    private boolean isVisible;
    private String description;
    private List<FilterFunctionItem> v;

    public FilterInfoBean(){

    }

    public FilterInfoBean(String k){
        this.k = k;
    }

    public String getK() {
        return k;
    }

    public void setK(String k) {
        this.k = k;
    }

    public boolean isIsVisible() {
        return isVisible;
    }

    public void setIsVisible(boolean isVisible) {
        this.isVisible = isVisible;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public List<FilterFunctionItem> getV() {
        return v;
    }

    public void setV(List<FilterFunctionItem> v) {
        this.v = v;
    }

    @Override
    public String toString() {
        return "FilterInfoBean{" +
                "k='" + k + '\'' +
                ", isVisible=" + isVisible +
                ", description='" + description + '\'' +
                ", v=" + v +
                '}';
    }
}

此时再运行程序,即可正常解析出来了。

这里写图片描述

运行之后的日志打印

这里写图片描述


作者:欧阳鹏 欢迎转载,与人分享是进步的源泉!
转载请保留原文地址:https://blog.csdn.net/ouyang_peng/article/details/82426092

☞ 本人QQ: 3024665621
☞ QQ交流群: 123133153
☞ github.com/ouyangpeng
[email protected]

如果本文对您有所帮助,欢迎您扫码下图所示的支付宝和微信支付二维码对本文进行打赏。

这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq446282412/article/details/82492314