繁体   English   中英

将字符串转换为 ArrayList<string> 使用 GSON</string>

[英]Convert String to ArrayList<String> using GSON

我正在尝试将 JSON 数据反序列化为 POJO。

问题是列表 object 以字符串形式出现,而 gson 给出了 IllegalStateExceptioState。 如何使用 gson 将字符串解析为 ArrayList 的列表?

JSON 数据

{
   "report_id":1943,
   "history_id":3302654,
   "project_id":null,
   "owner_emails":"[\"abcd@xyz.com\"]",
   "message":"Array\n(\n    [name] => SOMENAME\n    [age] => 36\n    [gender] => male\n)\n"
}

POJO:

    public class EventData {
    
        private static Gson gson = new Gson();
    
        @SerializedName("report_id")
        public String reportID;
    
        @SerializedName("history_id")
        public String historyID;
    
        @SerializedName("project_id")
        public String projectID;
    
        @SerializedName("owner_emails")
        public ArrayList<String> ownerEmails = new ArrayList<String>();
    
        @SerializedName("message")
        public String message;
    
    
        @SerializedName("title")
        public String title;
    
        public CrawlerNotifiedEventData(){
            this.projectID = "Undefined";
            this.reportID = "Undefined";
            this.historyID = "Undefined";
            this.title = "";
        }
    
        public String toJson(boolean base64Encode) throws java.io.UnsupportedEncodingException{
            
            String json = gson.toJson(this, CrawlerNotifiedEventData.class);
            
            if(base64Encode)
                return Base64.getEncoder().encodeToString(json.getBytes("UTF8"));
    
            return json;
        }
    
        public String toJson() throws java.io.UnsupportedEncodingException{
            return this.toJson(false);
        }
    
        public static EventData builder(String json){
            return gson.fromJson(json, EventData.class);   
        }
    }

反序列化:

EventData eventData = EventData.builder(json);

反序列化时出现以下错误

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 252 path $.owner_emails

在不需要的地方将结构化数据装箱是跨不同序列化方法的一个非常常见的设计问题。 幸运的是,Gson 可以处理诸如owner_emails之类的字段(当然不能处理message )。

仅仅创建一个类型适配器工厂,而不是通过替换原始类型并做更多工作来为特定类型创建类型适配器。 适配器应该将有效负载作为字符串读取,并将字符串反序列化委托给它所替代的类型适配器。

public final class JsonStringBoxTypeAdapterFactory
        implements TypeAdapterFactory {

    private JsonStringBoxTypeAdapterFactory() {
    }

    @Override
    public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
        final TypeAdapter<T> adapter = gson.getAdapter(typeToken);
        return new TypeAdapter<T>() {
            @Override
            public void write(final JsonWriter out, final T value) {
                throw new UnsupportedOperationException(); // TODO
            }

            @Override
            public T read(final JsonReader in)
                    throws IOException {
                return adapter.fromJson(in.nextString());
            }
        };
    }

}
@AllArgsConstructor
@ToString
@EqualsAndHashCode
final class EventData {

    @SerializedName("owner_emails")
    @JsonAdapter(JsonStringBoxTypeAdapterFactory.class)
    List<String> ownerEmails;

}

下面的单元测试将是绿色的:

final EventData eventData = gson.fromJson(json, EventData.class);
Assertions.assertEquals(new EventData(ImmutableList.of("abcd@xyz.com")), eventData);

而已。

“owner_emails”目前是一个字符串,如下所示

"owner_emails":"[\"abcd@xyz.com\"]"

它应该是

"owner_emails": ["abcd@xyz.com"]

被视为数组。 您可以手动删除引号并对其进行解析。

或者您可以使用JsonElement中的 JsonElement 对其进行解析

您可以使用jackson 库中的 ObjectMapper 进行此转换。

转换示例代码::

public <T> T mapResource(Object resource, Class<T> clazz) {
        try {
            return objectMapper.readValue(objectMapper.writeValueAsString(resource), clazz);
        } catch (IOException ex) {
            throw new Exception();
        }
    }

将 model 修改为如下列表

 public class Reportdata{
   
   private List<String> owner_emails = new ArrayList(); 

   @JsonDeserialize(contentAs = CustomClass.class)
   private List<CustomClass> customClassList =  new ArrayList();  
   ....// setter and getter
}

除此之外,在创建 ObjectMapper object 时,您可以传递或注册模块/您的自定义模块以在 object 中进行反序列化,如下所示。

objectMapper.setDefaultPropertyInclusion(Include.NON_EMPTY);
objectMapper.disable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
objectMapper.registerModule(new JavaTimeModule());

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM