为什么在转换为JSON时相关实体被转义?

huangapple go评论77阅读模式
英文:

Why are related entities being escaped when converted to JSON?

问题

我有一个Spring MVC控制器,通过查询获取一些实体。这些实体有一个相关的实体被“急切地”获取。然而,当我使用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;
}

// 实体 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

似乎出现在将相关模型序列化,然后附加到模型时发生,然后再次进行序列化。不确定如何阻止它。

英文:

I have a Spring MVC controller which fetches some entities via a query. These entities have a related entity that is eagerly fetched. However, when I use JSONObject.toString() it escapes the related model data:

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

The value in the language property is an escaped JSON object from the related entity. Why is it being escaped like that? How do I prevent it?

// Entity Reg

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

// Entity Language

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

    
    @OneToMany(fetch = FetchType.EAGER, mappedBy = &quot;language&quot;)
    private Set&lt;CmsRegions&gt; regions;
    
}

// Controller

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

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

...

Payload is just a POJO that is the data object we use to transmit data back from the API.

Why is language getting escaped? Is there an annotation I am missing?

UPDATE

I know that this is not JSONObject doing it, as I created a test case here:

https://repl.it/repls/GlossyScaredLock

It seems as though the occurrence happens when the related model is serialized, then attached to the model, which is then serialized. Not sure how to prevent it .

答案1

得分: 0

这是由于序列化造成的,为了使消息能够被正确解析,某些字符被替换为以下内容:

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

你可以使用 Apache Commons Lang 中的 StringEscapeUtils.unescapeJava(stringToUnEscape) 方法,在解析后移除这些转义。

英文:

This happens due to the serialization, there are some chars which are replaced in order for the message to be parsed properly :

Backspace is replaced with \b,
Form feed is replaced with \f,
Newline is replaced with \n,
Carriage return is replaced with \r,
Tab is replaced with \t,
Double quote is replaced with &quot;,
Backslash is replaced with \

You can use StringEscapeUtils.unescapeJava(stringToUnEscape) from Apache Commons lang in order to remove those escaping after parsed.

huangapple
  • 本文由 发表于 2020年9月16日 02:29:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/63907862.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定