【问题标题】:Gson.fromJson(json, Custom.class) empty stringGson.fromJson(json, Custom.class) 空字符串
【发布时间】:2019-06-16 22:05:03
【问题描述】:

我正在开发一个小型网络应用程序。

这是我的问题:

当用户尝试在我的数据表中添加新记录时执行此操作

@RequestMapping(value="/saveJokerRule", method= RequestMethod.POST, consumes= "application/json", produces = "application/json")
@ResponseBody
public String saveJokerRule(@RequestBody String json) {
    System.out.println("JSON EDITOR:" + json.toString());
    EditorResponse editorResponse = new EditorResponse();

    JokerRuleForm jokerRuleForm = new GsonBuilder().serializeNulls().create().fromJson(json, JokerRuleForm.class);

    ...
}

这是服务器接收并由系统调用打印的有效 json:

{"action":"create","data":{"0":{"jokerRule":{"group":1,"campaignPhase":"","dailyLimit":"","weeklyLimit":"","monthlyLimit":"","validFrom":"","activity":1}}}}

这就是 JokerRuleForm 类

public class JokerRuleForm {
    @Expose
    String action;

    @Expose
    @SerializedName("data")
    Map<String, JokerRuleView> data;

    ...
}

这就是 JokerRuleView 类

public class JokerRuleView {

String idJokerRule;

private AgentGroup group;

private JokerRule jokerRule;

private Activity activity;

public class JokerRule{

    private String campaignPhase;
    private Integer dailyLimit;
    private Integer weeklyLimit;
    private Integer monthlyLimit;
    private Date validFrom;
    private Date dateUpdate;
    private String group;
    private String activity;
    /**
     * @return the campaignPhase
     */
    public String getCampaignPhase() {
        return campaignPhase;
    }
    /**
     * @param campaignPhase the campaignPhase to set
     */
    public void setCampaignPhase(String campaignPhase) {
        this.campaignPhase = campaignPhase;
    }
    /**
     * @return the dailyLimit
     */
    public Integer getDailyLimit() {
        return dailyLimit;
    }
    /**
     * @param dailyLimit the dailyLimit to set
     */
    public void setDailyLimit(Integer dailyLimit) {
        this.dailyLimit = dailyLimit;
    }
    /**
     * @return the weeklyLimit
     */
    public Integer getWeeklyLimit() {
        return weeklyLimit;
    }
    /**
     * @param weeklyLimit the weeklyLimit to set
     */
    public void setWeeklyLimit(Integer weeklyLimit) {
        this.weeklyLimit = weeklyLimit;
    }
    /**
     * @return the monthlyLimit
     */
    public Integer getMonthlyLimit() {
        return monthlyLimit;
    }
    /**
     * @param monthlyLimit the monthlyLimit to set
     */
    public void setMonthlyLimit(Integer monthlyLimit) {
        this.monthlyLimit = monthlyLimit;
    }
    /**
     * @return the validFrom
     */
    public Date getValidFrom() {
        return validFrom;
    }
    /**
     * @param validFrom the validFrom to set
     */
    public void setValidFrom(Date validFrom) {
        this.validFrom = validFrom;
    }
    /**
     * @return the dateUpdate
     */
    public Date getDateUpdate() {
        return dateUpdate;
    }
    /**
     * @param dateUpdate the dateUpdate to set
     */
    public void setDateUpdate(Date dateUpdate) {
        this.dateUpdate = dateUpdate;
    }
    /**
     * @return the group
     */
    public String getGroup() {
        return group;
    }
    /**
     * @param group the group to set
     */
    public void setGroup(String group) {
        this.group = group;
    }
    /**
     * @return the activity
     */
    public String getActivity() {
        return activity;
    }
    /**
     * @param activity the activity to set
     */
    public void setActivity(String activity) {
        this.activity = activity;
    }

}

public class Activity {
    String idActivity;
    String name;

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return the idGroup
     */
    public String getIdActivity() {
        return idActivity;
    }

    /**
     * @param idGroup the idGroup to set
     */
    public void setIdActivity(String idActivity) {
        this.idActivity = idActivity;
    }
}

public class AgentGroup {

    String idGroup;
    String name;

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return the idGroup
     */
    public String getIdGroup() {
        return idGroup;
    }

    /**
     * @param idGroup the idGroup to set
     */
    public void setIdGroup(String idGroup) {
        this.idGroup = idGroup;
    }

}

/**
 * @return the idJokerRule
 */
public String getIdJokerRule() {
    return idJokerRule;
}

/**
 * @param idJokerRule the idJokerRule to set
 */
public void setIdJokerRule(String idJokerRule) {
    this.idJokerRule = idJokerRule;
}

/**
 * @return the agentGroup
 */
public AgentGroup getGroup() {
    return group;
}

/**
 * @param agentGroup the agentGroup to set
 */
public void setGroup(AgentGroup group) {
    this.group = group;
}

/**
 * @return the jokerRule
 */
public JokerRule getJokerRule() {
    return jokerRule;
}

/**
 * @param jokerRule the jokerRule to set
 */
public void setJokerRule(JokerRule jokerRule) {
    this.jokerRule = jokerRule;
}

/**
 * @return the activity
 */
public Activity getActivity() {
    return activity;
}

/**
 * @param activity the activity to set
 */
public void setActivity(Activity activity) {
    this.activity = activity;
}

}

 JokerRuleForm jokerRuleForm = new GsonBuilder().serializeNulls().create().fromJson(json, JokerRuleForm.class);

执行此行时,我得到一个 NumberFormatException 空字符串,我认为它是 dailyLimit 或 date 的错误,因为它是空的,并且 fromJson() 方法无法完成他需要做的事情。

我读过一些关于 TypeAdapter 的文章,似乎适合我的情况,但我真的不知道如何继续,我不确定是否是一个有效的解决方案。

有人可以帮我吗?

【问题讨论】:

    标签: java json datatable gson fromjson


    【解决方案1】:

    限制字段,例如dailyLimit 是 JSON 中的空字符串。这是在 JsonParseException when encountering an empty value for an int or long #472 问题中提出的,但 Gson 团队关闭了它,因为将 "" 解析为 int 是没有意义的。

    其中一位用户提供了a solution in his comment,它允许轻松解析数字值。我不会自己走这条路并修复 JSON,但这取决于你:

    public static final TypeAdapter<Number> UNRELIABLE_INTEGER = new TypeAdapter<Number>() {
        @Override
        public Number read(JsonReader in) throws IOException {
            JsonToken jsonToken = in.peek();
            switch (jsonToken) {
                case NUMBER:
                case STRING:
                    String s = in.nextString();
                    try {
                        return Integer.parseInt(s);
                    } catch (NumberFormatException ignored) {
                    }
                    try {
                        return (int)Double.parseDouble(s);
                    } catch (NumberFormatException ignored) {
                    }
                    return null;
                case NULL:
                    in.nextNull();
                    return null;
                case BOOLEAN:
                    in.nextBoolean();
                    return null;
                default:
                    throw new JsonSyntaxException("Expecting number, got: " + jsonToken);
            }
        }
        @Override
        public void write(JsonWriter out, Number value) throws IOException {
            out.value(value);
        }
    };
    public static final TypeAdapterFactory UNRELIABLE_INTEGER_FACTORY = TypeAdapters.newFactory(int.class, Integer.class, UNRELIABLE_INTEGER);
    
    Gson gson = new GsonBuilder()
        .registerTypeAdapterFactory(UNRELIABLE_INTEGER_FACTORY)
        .create();
    

    【讨论】:

    • 太快了,谢谢!我会尽快尝试实施您的解决方案,再次感谢您!
    • 我又来了,但没有正面消息。这行代码我得到了同样的例外: JokerRuleFormjokerRuleForm = new GsonBuilder() .registerTypeAdapterFactory(UNRELIABLE_INTEGER_FACTORY) .create() .fromJson(json, JokerRuleForm.class);如果我在 read() 和 write() 方法中放置一个调试点,它永远不会停止。似乎从未被调用过。 @卡罗尔
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-09
    • 1970-01-01
    • 2018-10-31
    • 2018-11-24
    • 2020-07-10
    相关资源
    最近更新 更多