shenyu icon indicating copy to clipboard operation
shenyu copied to clipboard

[BUG] <title>When the class gsonutils is converted to int type, it will become double type

Open gongzhibo opened this issue 2 years ago • 9 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Current Behavior

[{params={date={intervalDay=0.0}, domain=weather, showDay=今天, action=query, location=[{"city":"北京市","country":"CHN","province":"北京市"}], type=天气, deviceLocation=西安市}}]

Expected Behavior

[{params={date={intervalDay=0}, domain=weather, showDay=今天, action=query, location=[{"city":"北京市","country":"CHN","province":"北京市"}], type=天气, deviceLocation=西安市}}]

Steps To Reproduce

org.apache.shenyu.common.utils.GsonUtils#fromList

Environment

ShenYu version(s):

Debug logs

No response

Anything else?

No response

gongzhibo avatar Jul 07 '22 07:07 gongzhibo

Can you provide a minimal, runnable demo?

impactCn avatar Jul 07 '22 08:07 impactCn

Can you provide a minimal, runnable demo?

[ { "params":{ "date":{ "intervalDay":0 }, "domain":"weather", "showDay":"今天", } } ]

gongzhibo avatar Jul 07 '22 09:07 gongzhibo

@gongzhibo Hi, please add demo to org.apache.shenyu.common.utils.GsonUtilsTest.

loongs-zhang avatar Aug 01 '22 08:08 loongs-zhang

I reproduced the issue with the following code

        String testJson = "[{\"params\":{\"date\":{\"intervalDay\":0},\"domain\":\"weather\",\"showDay\":\"今天\"}}]";
        List<Object> testList = GsonUtils.getInstance().fromList(testJson,Object.class);
        System.out.println(testList);

In this code, I use Object.class to serialize the json string, the result is as follows: [{params={date={intervalDay=0.0}, domain=weather, showDay=今天}}]

But when I defined a class to match the json String, the issue disappear. The code

static class TestParams{
        Params params;
        static class Params{
            private String domain;
            private String showDay;
            private Map<String,Integer> date;
        }

      // setter and getter

TestClass

        String testJson = "[{\"params\":{\"date\":{\"intervalDay\":0},\"domain\":\"weather\",\"showDay\":\"今天\"}}]";
        List<TestParams> testList = GsonUtils.getInstance().fromList(testJson,TestParams.class);
        assertEquals(testList.get(0).getParams().getDate().get("intervalDay"),0);

I think the issue may be related to gson configuration.

hujun8610 avatar Aug 13 '22 10:08 hujun8610

I follow this problem.

impactCn avatar Aug 15 '22 03:08 impactCn

@hujun8610 hi.

image

If the object type is used, the ObjectTypeAdapter adapter is used by default in gson. Convert numbers to double type. This is a problem with the gson framework.

impactCn avatar Aug 15 '22 04:08 impactCn

@impactCn thanks for your reply. In current situation,we can use specific type instead of object,but how we can solve the problem.

hujun8610 avatar Aug 15 '22 07:08 hujun8610

We'll be releasing a new version these days, and in the next version we'll have a custom adapter to fix this.

Thank you very much for asking this question.

impactCn avatar Aug 15 '22 07:08 impactCn

@impactCn Someone has found the issue,I found it in https://github.com/google/gson/pull/1290,gson has solve the problem. I solve it using the following code

    private static final Gson GSON = new GsonBuilder()
            .registerTypeAdapter(String.class, new StringTypeAdapter())
            .registerTypeHierarchyAdapter(Pair.class, new PairTypeAdapter())
            .registerTypeHierarchyAdapter(Duration.class, new DurationTypeAdapter())
            .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) // new code
            .create();

when the ToNumberPolicy is LONG_OR_DOUBLE, it means gson will try to parse a number as a Long, otherwise then try to parse it as a Double, if the number cannot be parsed as a Long. Hope to help you,thanks!

hujun8610 avatar Aug 15 '22 12:08 hujun8610