alibaba / fastjson2

🚄 FASTJSON2 is a Java JSON library with excellent performance.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

GeoJsonPoint解析问题[BUG]

ocean23 opened this issue · comments

commented

问题描述

简要描述您碰到的问题。
以下是json数据

{
    "_id":
    {
        "$oid": "61a591ef96eb001a9437d6c4"
    },
    "gpsAddress":
    {
        "type": "Point",
        "coordinates":
        [
            114.027285886961,
            22.6741582981732
        ]
    }
}

这是对应的Mapper对象的属性

private GeoJsonPoint gpsAddress;

对于1的版本,虽然调用JSON.parseObject解析出来的对象也是不正确的,内容都是0但是至少不会报错,但是2的版本后就直接报错了,是否考虑用1的解决方案假如找不到默认的构造函数就返回默认的内容就行,不要报错

环境信息

请填写以下信息:

  • OS信息: [e.g.:CentOS 8.4.2105 4Core 3.10GHz 16 GB]
  • JDK信息: [e.g.:Openjdk 1.8.0_312]
  • 版本信息:[e.g.:Fastjson2 2.x.x]

报错信息

请复制并粘贴任何相关的日志输出。
Exception in thread "main" java.lang.UnsupportedOperationException
at java.base/java.util.AbstractList.add(AbstractList.java:153)
at java.base/java.util.AbstractList.add(AbstractList.java:111)
at com.alibaba.fastjson2.reader.FieldReaderCollectionMethodReadOnly.accept(FieldReaderCollectionMethodReadOnly.java:80)
at com.alibaba.fastjson2.reader.ObjectReaderNoneDefaultConstrutor.readObject(ObjectReaderNoneDefaultConstrutor.java:260)
at com.alibaba.fastjson2.reader.FieldReaderObjectMethod.readFieldValue(FieldReaderObjectMethod.java:78)
at com.alibaba.fastjson2.reader.ObjectReader.readObject(ObjectReader.java:371)
at com.alibaba.fastjson2.JSON.parseObject(JSON.java:146)

commented

有问题的写法

CoreCompanyDO coreCompanyDO = JSON.parseObject(ss, CoreCompanyDO.class);

临时的解决方案

JSONObject jsonObject = JSON.parseObject(ss, JSONObject.class);
CoreCompanyDO coreCompanyDO = jsonObject.toJavaObject(CoreCompanyDO.class);

通过JSONObject中转一下就可以达到1.0版本的效果, 暂时先这样解决

GeoJsonPoint 这个类的代码能提供下么?

commented

@wenshao hello温少,我想参与到fastjson2这个项目中来,可否大概说一下这个bug的思路吗?我尝试修复一下再发一个PR。因为之前没怎么看这个项目的源码。

commented

@wenshao 源码在spring-data-mongodb这个jar
image

这个我case有点特别,我还要想下怎么实现。这个JSON数据是怎么来的?

commented

这个数据前端是通过百度地直获取经纬度然后塞进来的

GeoJsonPoint geoJsonPoint = new GeoJsonPoint(gpsAddress.getLongitude(), gpsAddress.getLatitude());
coreCompanyDO.setGpsAddress(geoJsonPoint);

在spring的框架下存储都是没问题的,因为针对GeoJsonPoint内置的对应的converter

	private static void registerDeserializersIn(SimpleModule module) {

		module.addDeserializer(GeoJsonPoint.class, new GeoJsonPointDeserializer());
		module.addDeserializer(GeoJsonMultiPoint.class, new GeoJsonMultiPointDeserializer());
		module.addDeserializer(GeoJsonLineString.class, new GeoJsonLineStringDeserializer());
		module.addDeserializer(GeoJsonMultiLineString.class, new GeoJsonMultiLineStringDeserializer());
		module.addDeserializer(GeoJsonPolygon.class, new GeoJsonPolygonDeserializer());
		module.addDeserializer(GeoJsonMultiPolygon.class, new GeoJsonMultiPolygonDeserializer());
	}

这段代码在这个类里面
image
现在出现问题是我们现在是监听mongodb的changestream没有通过spring,手动通过fastJson把json转为对象时出错了,因为在这个过程中没有经过converter。

https://oss.sonatype.org/content/repositories/snapshots/com/alibaba/fastjson2/

你可以使用fastjson2-extension 2.0.4-SNAPSHOT版本验证下

需要加上如下依赖:

<dependency>
     <groupId>com.alibaba.fastjson2</groupId>
     <artifactId>fastjson2-extension</artifactId>
     <version>2.0.4-SNAPSHOT</version>
</dependency>
public class Issue256 {

    @BeforeEach
    public void init() {
        JSON.register(GeoJsonReaderModule.INSTANCE);
    }

    @Test
    public void test() {
        String str = "{\n" +
                "    \"_id\":\n" +
                "    {\n" +
                "        \"$oid\": \"61a591ef96eb001a9437d6c4\"\n" +
                "    },\n" +
                "    \"gpsAddress\":\n" +
                "    {\n" +
                "        \"type\": \"Point\",\n" +
                "        \"coordinates\":\n" +
                "        [\n" +
                "            114.027285886961,\n" +
                "            22.6741582981732\n" +
                "        ]\n" +
                "    }\n" +
                "}";

        Bean bean = JSON.parseObject(str, Bean.class);
        assertNotNull(bean.gpsAddress);
        assertEquals(114.027285886961D, bean.gpsAddress.getX());
        assertEquals(22.6741582981732D, bean.gpsAddress.getY());
    }

    public static class Bean {
        public GeoJsonPoint gpsAddress;
    }
}
commented

Cool 👍 可以了。因为是spring boot的项目,我计划下面的方式添加初始化,不知道有没有更好的方案,请指教哈 @wenshao

@Slf4j
@Component
public class JsonInit implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        JSON.register(GeoJsonReaderModule.INSTANCE);
    }
}

@ocean23
最新版本的快照2.0.4-SNAPSHOT中,package从com.alibaba.fastjson2.support.spring.mongodb改为com.alibaba.fastjson2.support.spring.data.mongodb了

commented

@wenshao 好的,谢谢温少。

https://github.com/alibaba/fastjson2/releases/tag/2.0.4
问题已经在2.0.4版本中修复,请用新版本