如何在将 JSON 解析为地图时忽略特定字段
How to ignore a specific field while parsing a JSON into map
我想将下面的 JSON 解析为 POJO。我正在使用杰克逊来解析 json.
{
"totalSize": 4,
"done": true,
"records": [
{
"attributes": {
"type": "oppor",
"url": "/service/oppor/456"
},
"AccountId": "123",
"Id": "456",
"ProposalID": "103"
}
]
}
在上面的JSON中,字段"totalSize"、"done"、"records"和"attributes"是已知字段。而 "AccountId"、"Id" 和 "ProposalID" 是未知字段。在上面的 JSON 中,我不需要 "attributes" 成为我的 bean 对象的一部分。
这里是我的 JSON
的等效 bean class
public class Result {
private int totalSize;
private boolean done;
private List<Map<String, String>> records;
public int getTotalSize() {
return totalSize;
}
public void setTotalSize(int totalSize) {
this.totalSize = totalSize;
}
public boolean isDone() {
return done;
}
public void setDone(boolean done) {
this.done = done;
}
public List<Map<String,String>> getRecords() {
return records;
}
public void setRecords(List<Map<String, String>> records) {
this.records = records;
}
}
因此记录元素中有未知字段我刚刚使用列表获取bean 中的结果元素。在此地图中,我不需要字段 "attributes"。解析时如何忽略它?
下面是我得到的异常,因为属性不是字符串元素。
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token
at [Source: [B@66fdec9; line: 1, column: 40] (through reference chain: com.sample.json.Result["records"])
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:691)
at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:46)
at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:11)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBindStringMap(MapDeserializer.java:430)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:312)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:26)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:227)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:204)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:23)
为属性创建一个新的 POJO class,
public class Result {
private int totalSize;
private boolean done;
private List<Attributes> records;
// Your Getters & Setters
}
public class Attributes{
List<Map<String,String>> attributes;
// Add other variables if necessary like AccountId, etc.,
// Your Getters & Setters
}
1) 创建记录 class 对象
2) 在你不会的字段上添加@JsonIgnore 注解
public class Result {
private int totalSize;
private boolean done;
private Record records;
[..]
}
public class Record {
@JsonIgnore
private Map<String, String> attributes;
private int accountID;
private int id;
private int approvalID;
[..]
}
更新 2015/08/29:
正如您所说
I achieved dynamic field support by parsing the JSON into map. Ignoring bad JSON element is what pending
我建议您处理原始 JSONObject 以从中删除 "attributes"
元素。
原始JSONObject,例如:
{
"totalSize": 4,
"done": true,
"records": [
{
"attributes": {
"type": "oppor",
"url": "/service/oppor/456"
},
"AccountId": "123",
"Id": "456",
"ProposalID": "103"
}
]
}
经过处理后,新的 JSONObject 将如下所示:
{
"records": {
"AccountId": "123",
"Id": "456",
"ProposalID": "103"
},
"totalSize": 4,
"done": true
}
使用如下代码:
JSONObject jsonObject;
try {
jsonObject = new JSONObject(jsonString1);
JSONArray jsonArray = new JSONArray(jsonObject.get("records").toString());
JSONObject jsonObject1 = jsonArray.getJSONObject(0);
jsonObject1.remove("attributes");
jsonObject.put("records", jsonObject1);
} catch (JSONException e) {
e.printStackTrace();
}
然后,使用您自己的代码 achieved dynamic field support by parsing the JSON into map
。
更新结束 2015/08/29
我建议你在这种情况下使用 Gson
和 transient
像这样
String jsonString1 = "{\n" +
" \"totalSize\": 4,\n" +
" \"done\": true,\n" +
" \"records\": [\n" +
" {\n" +
" \"attributes\": {\n" +
" \"type\": \"oppor\",\n" +
" \"url\": \"/service/oppor/456\"\n" +
" },\n" +
" \"AccountId\": \"123\",\n" +
" \"Id\": \"456\",\n" +
" \"ProposalID\": \"103\"\n" +
" }\n" +
" ]\n" +
"}";
Gson gson = new Gson();
Result result1 = gson.fromJson(jsonString1, Result.class);
你的类,关注transient
:
public class Result {
private int totalSize;
private boolean done;
private List<Record> records;
}
public class Record {
private transient Map<String, String> attributes;
private int AccountId;
private int Id;
private int ProposalID;
}
你会得到结果:
P/S:我在 Android Studio 中测试过 :)
更新:
String jsonString1 = "{\n" +
" \"totalSize\": 4,\n" +
" \"done\": true,\n" +
" \"records\": [\n" +
" {\n" +
" \"attributes\": {\n" +
" \"type\": \"oppor\",\n" +
" \"url\": \"/service/oppor/456\"\n" +
" },\n" +
" \"AccountId\": \"123\",\n" +
" \"Id\": \"456\",\n" +
" \"ProposalID\": \"103\"\n" +
" }\n" +
" ]\n" +
"}";
Gson gson = new Gson();
Object object = gson.fromJson(jsonString1, Object.class);
Map<String, String> stringMap = (Map<String, String>) object;
Result myResult = new Result();
Iterator entries = stringMap.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry entry = (Map.Entry) entries.next();
String key = entry.getKey().toString();
String value = entry.getValue().toString();
switch (key) {
case "totalSize":
myResult.totalSize = (int) Double.parseDouble(entry.getValue().toString());
break;
case "done":
myResult.done = Boolean.valueOf(entry.getValue().toString());
break;
case "records":
try{
Object object1 = entry.getValue();
List<Object> objectList = (List<Object>) object1;
Map<String, Object> stringMap2 = (Map<String, Object>) objectList.get(0);
Map<String, String> recordMap = new HashMap<>();
Iterator entries2 = stringMap2.entrySet().iterator();
while (entries2.hasNext()) {
Map.Entry entry2 = (Map.Entry) entries2.next();
String key2 = entry2.getKey().toString();
String value2 = entry2.getValue().toString();
if (!"attributes".equals(key2)) {
recordMap.put(key2, value2);
}
entries2.remove();
}
myResult.records = recordMap;
} catch (Exception e) {
e.printStackTrace();
}
break;
}
entries.remove();
}
类:
public class Result {
private int totalSize;
private boolean done;
private Map<String, String> records;
}
调试结果:
我建议使用 [Google gson API][1]'s @Expose annotation.(如果您的环境允许这样做)。
您可以简单地注释生成的 json 文件中需要的字段(使用 @Expose
),并将其保留在其他字段中。并在生成 json 期间,使用 API 方法,excludeFieldsWithoutExposeAnnotation
.
示例可见here.
注意 :在您的示例中,将您的 Result
视为主 POJO,而 records
是另一个具有 attributes
,accountId
等字段。
那么它们之间就有了has-a关系(Java composition)。
之后,您可以调用 Json 到 pojo 转换,如下所示 --
com.google.gson.Gson gson = new com.google.gson.GsonBuilder()
.excludeFieldsWithoutExposeAnnotation().create();
Result result= gson.fromJson(yourjsonString, Result.class);
如果您有不想映射的特定字段,您可以在字段名称上使用 @JsonIgnore 注释
public class MyJsonObj{
@JsonProperty("name")
String fieldName
@JsonIgnore
String fieldNameIgnored;
}
如果你想忽略你的POJO中没有提到的所有字段,你可以使用
@JsonIgnoreProperties 注释超过 class
@JsonIgnoreProperties(ignoreUnknown = true)
public class MyJsonObj{
strong text
}
我想将下面的 JSON 解析为 POJO。我正在使用杰克逊来解析 json.
{
"totalSize": 4,
"done": true,
"records": [
{
"attributes": {
"type": "oppor",
"url": "/service/oppor/456"
},
"AccountId": "123",
"Id": "456",
"ProposalID": "103"
}
]
}
在上面的JSON中,字段"totalSize"、"done"、"records"和"attributes"是已知字段。而 "AccountId"、"Id" 和 "ProposalID" 是未知字段。在上面的 JSON 中,我不需要 "attributes" 成为我的 bean 对象的一部分。
这里是我的 JSON
的等效 bean classpublic class Result {
private int totalSize;
private boolean done;
private List<Map<String, String>> records;
public int getTotalSize() {
return totalSize;
}
public void setTotalSize(int totalSize) {
this.totalSize = totalSize;
}
public boolean isDone() {
return done;
}
public void setDone(boolean done) {
this.done = done;
}
public List<Map<String,String>> getRecords() {
return records;
}
public void setRecords(List<Map<String, String>> records) {
this.records = records;
}
}
因此记录元素中有未知字段我刚刚使用列表获取bean 中的结果元素。在此地图中,我不需要字段 "attributes"。解析时如何忽略它? 下面是我得到的异常,因为属性不是字符串元素。
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token
at [Source: [B@66fdec9; line: 1, column: 40] (through reference chain: com.sample.json.Result["records"])
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:691)
at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:46)
at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:11)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer._readAndBindStringMap(MapDeserializer.java:430)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:312)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer.deserialize(MapDeserializer.java:26)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:227)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:204)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:23)
为属性创建一个新的 POJO class,
public class Result {
private int totalSize;
private boolean done;
private List<Attributes> records;
// Your Getters & Setters
}
public class Attributes{
List<Map<String,String>> attributes;
// Add other variables if necessary like AccountId, etc.,
// Your Getters & Setters
}
1) 创建记录 class 对象
2) 在你不会的字段上添加@JsonIgnore 注解
public class Result {
private int totalSize;
private boolean done;
private Record records;
[..]
}
public class Record {
@JsonIgnore
private Map<String, String> attributes;
private int accountID;
private int id;
private int approvalID;
[..]
}
更新 2015/08/29:
正如您所说
I achieved dynamic field support by parsing the JSON into map. Ignoring bad JSON element is what pending
我建议您处理原始 JSONObject 以从中删除 "attributes"
元素。
原始JSONObject,例如:
{
"totalSize": 4,
"done": true,
"records": [
{
"attributes": {
"type": "oppor",
"url": "/service/oppor/456"
},
"AccountId": "123",
"Id": "456",
"ProposalID": "103"
}
]
}
经过处理后,新的 JSONObject 将如下所示:
{
"records": {
"AccountId": "123",
"Id": "456",
"ProposalID": "103"
},
"totalSize": 4,
"done": true
}
使用如下代码:
JSONObject jsonObject;
try {
jsonObject = new JSONObject(jsonString1);
JSONArray jsonArray = new JSONArray(jsonObject.get("records").toString());
JSONObject jsonObject1 = jsonArray.getJSONObject(0);
jsonObject1.remove("attributes");
jsonObject.put("records", jsonObject1);
} catch (JSONException e) {
e.printStackTrace();
}
然后,使用您自己的代码 achieved dynamic field support by parsing the JSON into map
。
更新结束 2015/08/29
我建议你在这种情况下使用 Gson
和 transient
像这样
String jsonString1 = "{\n" +
" \"totalSize\": 4,\n" +
" \"done\": true,\n" +
" \"records\": [\n" +
" {\n" +
" \"attributes\": {\n" +
" \"type\": \"oppor\",\n" +
" \"url\": \"/service/oppor/456\"\n" +
" },\n" +
" \"AccountId\": \"123\",\n" +
" \"Id\": \"456\",\n" +
" \"ProposalID\": \"103\"\n" +
" }\n" +
" ]\n" +
"}";
Gson gson = new Gson();
Result result1 = gson.fromJson(jsonString1, Result.class);
你的类,关注transient
:
public class Result {
private int totalSize;
private boolean done;
private List<Record> records;
}
public class Record {
private transient Map<String, String> attributes;
private int AccountId;
private int Id;
private int ProposalID;
}
你会得到结果:
P/S:我在 Android Studio 中测试过 :)
更新:
String jsonString1 = "{\n" +
" \"totalSize\": 4,\n" +
" \"done\": true,\n" +
" \"records\": [\n" +
" {\n" +
" \"attributes\": {\n" +
" \"type\": \"oppor\",\n" +
" \"url\": \"/service/oppor/456\"\n" +
" },\n" +
" \"AccountId\": \"123\",\n" +
" \"Id\": \"456\",\n" +
" \"ProposalID\": \"103\"\n" +
" }\n" +
" ]\n" +
"}";
Gson gson = new Gson();
Object object = gson.fromJson(jsonString1, Object.class);
Map<String, String> stringMap = (Map<String, String>) object;
Result myResult = new Result();
Iterator entries = stringMap.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry entry = (Map.Entry) entries.next();
String key = entry.getKey().toString();
String value = entry.getValue().toString();
switch (key) {
case "totalSize":
myResult.totalSize = (int) Double.parseDouble(entry.getValue().toString());
break;
case "done":
myResult.done = Boolean.valueOf(entry.getValue().toString());
break;
case "records":
try{
Object object1 = entry.getValue();
List<Object> objectList = (List<Object>) object1;
Map<String, Object> stringMap2 = (Map<String, Object>) objectList.get(0);
Map<String, String> recordMap = new HashMap<>();
Iterator entries2 = stringMap2.entrySet().iterator();
while (entries2.hasNext()) {
Map.Entry entry2 = (Map.Entry) entries2.next();
String key2 = entry2.getKey().toString();
String value2 = entry2.getValue().toString();
if (!"attributes".equals(key2)) {
recordMap.put(key2, value2);
}
entries2.remove();
}
myResult.records = recordMap;
} catch (Exception e) {
e.printStackTrace();
}
break;
}
entries.remove();
}
类:
public class Result {
private int totalSize;
private boolean done;
private Map<String, String> records;
}
调试结果:
我建议使用 [Google gson API][1]'s @Expose annotation.(如果您的环境允许这样做)。
您可以简单地注释生成的 json 文件中需要的字段(使用 @Expose
),并将其保留在其他字段中。并在生成 json 期间,使用 API 方法,excludeFieldsWithoutExposeAnnotation
.
示例可见here.
注意 :在您的示例中,将您的 Result
视为主 POJO,而 records
是另一个具有 attributes
,accountId
等字段。
那么它们之间就有了has-a关系(Java composition)。
之后,您可以调用 Json 到 pojo 转换,如下所示 --
com.google.gson.Gson gson = new com.google.gson.GsonBuilder()
.excludeFieldsWithoutExposeAnnotation().create();
Result result= gson.fromJson(yourjsonString, Result.class);
如果您有不想映射的特定字段,您可以在字段名称上使用 @JsonIgnore 注释
public class MyJsonObj{
@JsonProperty("name")
String fieldName
@JsonIgnore
String fieldNameIgnored;
}
如果你想忽略你的POJO中没有提到的所有字段,你可以使用 @JsonIgnoreProperties 注释超过 class
@JsonIgnoreProperties(ignoreUnknown = true)
public class MyJsonObj{
strong text
}