简体   繁体   中英

Gson.fromJson(json, Custom.class) empty string

i'm developing a small web application.

That's my problem:

This is executed when a user try to add a new record in my Datatable

@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);

    ...
}

This is the valid json received by the server and printed by a System call:

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

That's the JokerRuleForm classs

public class JokerRuleForm {
    @Expose
    String action;

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

    ...
}

That's the JokerRuleView class

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);

When executing this line i got a NumberFormatException empty string and i think it dailyLimit's or date's fault because it's empty and fromJson() method can't do what he need to do.

I've read something about a TypeAdapter that seems can fit to my case, but i don't really know how to proceed and i'm not sure is a valid solution.

Can someone help me?

The limit fields eg dailyLimit are empty strings in your JSON. This was suggested in JsonParseException when encountering an empty value for an int or long #472 issue but Gson team closed it because it makes no sense to parse "" as int .

One of the users provided a solution in his comment which allows to leniently parse the number values. I'd not go this route myself and fix JSON instead, but it's up to you:

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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM