首页 > 解决方案 > 为什么在转换为 JSON 时相关实体会被转义?

问题描述

我有一个 Spring MVC 控制器,它通过查询获取一些实体。这些实体具有被eagerly提取的相关实体。但是,当我使用JSONObject.toString()它时,它会转义相关的模型数据:

    {
        "totalRecords": 29,
        "hasErrors": false,
        "data": {
            "regs": [
                {
                    "is_active": 1,
                    "name": "NAR",
                    "modified": "09/14/2020 08:46 AM",
                    "language": "{\"name\":\"English\",\"id\":1,\"shortcode\":\"en\"}", <--
                    "id": 1,
                },
                {
                    "is_active": 1,
                    "name": "SAR",
                    "modified": "09/14/2020 08:46 AM",
                    "language": "{\"name\":\"English\",\"id\":1,\"shortcode\":\"en\"}", <--
                    "id": 2,
                }
            ]
        }
    }

属性中的值language是来自相关实体的转义 JSON 对象。为什么就这样被逃跑了?我该如何预防?

// 实体Reg

public class CmsRegions extends CmsModel implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    
    @JsonManagedReference
    @ManyToOne(optional = false, fetch = FetchType.EAGER, cascade = CascadeType.DETACH)
    @JoinColumn(name = "language_id", referencedColumnName = "id")
    private SysLanguages language;
}

// 实体语言

public class SysLanguages extends Model implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 100)
    @Column(name = "name")
    private String name;

    
    @OneToMany(fetch = FetchType.EAGER, mappedBy = "language")
    private Set<CmsRegions> regions;
    
}

// 控制器

...
   JSONArray objs  = new JSONArray();
   for (CmsRegions region : regions) {
                JSONObject jsonRegion = new JSONObject();
                
                jsonRegion.put("id", region.getId());
                jsonRegion.put("name", region.getName());
                jsonRegion.put("description", region.getDescription());
                jsonRegion.put("language", region.getLanguage());
                objs.put(jsonRegion);
   }

   String response = new JSONObject(payload).toString();

...

Payload只是一个 POJO,它是我们用来从 API 传回数据的数据对象。

为什么language要逃跑?我缺少注释吗?

更新

我知道这不是JSONObject这样做的,因为我在这里创建了一个测试用例:

https://repl.it/repls/GlossyScaredLock

似乎这种情况发生在相关模型被序列化,然后附加到模型,然后被序列化时。不知道如何防止它。

标签: javajsonspringhibernatejpa

解决方案


这是由于序列化而发生的,为了正确解析消息,有一些字符被替换:

退格替换为\b,换页符替换为\f,换行符替换为\n,回车替换为\r,制表符替换为\t,双引号替换为“,反斜杠替换为\

您可以使用 Apache Commons lang 中的 StringEscapeUtils.unescapeJava(stringToUnEscape) 来删除解析后的转义。


推荐阅读