[英]How to parse newline delimited Json response in Android?
Sample of NdJson
data: NdJson
数据样本:
{"type":"data","id":"xyz"}
{"type":"value","id":"xcf"}
....
....
Here is my Retrofit
and RxJava
code which is working fine for fetching data with the limit=1
ie {"type":"data","id":"xyz"}
. 这是我的
Retrofit
和RxJava
代码,适用于以limit=1
即{"type":"data","id":"xyz"}
来获取数据。
adapter.create(API.class).getData()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<APIData>() {
@Override
public void onCompleted() {}
@Override
public void onError(Throwable e) {}
@Override
public void onNext(APIData apidata) {}
});
Model class have only two parameter: 模型类只有两个参数:
public class APIData(){
private String type;
private String id;
..// Getter and setter for above two fields
}
public interface WarehouseAPI {
@GET("/search?limit=1")
public Observable<APIData> getdata ();
}
The error I am getting while replacing @GET("/search?limit=1")
with @GET("/search")
is Malformed JSON: Syntax error
. 而更换我正的错误
@GET("/search?limit=1")
与@GET("/search")
是Malformed JSON: Syntax error
。
How to proper parse the NdJson
? 如何正确解析
NdJson
?
Is there any way to store the response in List<APIData>
有什么方法可以将响应存储在
List<APIData>
Now I am trying to accept the generic Response
in observer: 现在,我试图在观察者中接受通用
Response
:
adapter.create(APIData.class).getdata()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Response>() {
@Override
public void onCompleted() {}
@Override
public void onNext(Response response) {}
});
But getting no suitable method found for subscribe(<anonymous Observer<Response>>)
但是
no suitable method found for subscribe(<anonymous Observer<Response>>)
However, I was doing some silly mistake and the error what I am getting in "Edit-1" section is fixed now. 但是,我犯了一些愚蠢的错误,并且在“ Edit-1”部分中得到的错误现在已修复。 Now I am getting
现在我得到
Error:retrofit.RetrofitError: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 2 column 2 path $
I assume that server response has the following format 我假设服务器响应具有以下格式
{"type":"data","id":"xyz"}\n{"type":"data","id":"xyz"}
The basic idea is to receive the response from the server as the String. 基本思想是从服务器接收响应作为字符串。 Split it into array like
response.split("\\n")
. 将其拆分为类似于
response.split("\\n")
数组。 Iterate through an Array creating a new json object for every array element. 遍历数组,为每个数组元素创建一个新的json对象。
I do realize it's quite time consuming as you've described in the comments. 我确实意识到,正如您在评论中所描述的那样,这非常耗时。 You can also try to play with String
replaceAll
method to transform each line into an array element and parse the whole string. 您也可以尝试使用String
replaceAll
方法将每一行转换成一个数组元素并解析整个字符串。 like 喜欢
String myResponse = "[" + response.replaceAll("/\n/", ",") + "]";
Gson gson = new Gson();
MyEntity[] arr = gson.fromJson(myResponse, MyEntity[].class);
In case of Retrofit. 如果进行改装。 You will have to use a custom Response Converter.
您将必须使用自定义响应转换器。 I won't write up the complete solution since you have found the way to get it done using custom Converter.
因为您已经找到了使用自定义Converter来完成该问题的方法,所以我不会写出完整的解决方案。
To make things work I had to add Custom converter
implements by Retrofit.Converter
: 为了使工作正常,我必须通过
Retrofit.Converter
添加Custom converter
工具:
public class CustomConverter implements Converter {
@Override
public Object fromBody(TypedInput body, Type type) throws ConversionException {
String text = null;
try {
text = fromStream(body.in());
} catch (IOException e) {
e.printStackTrace();
}
return text;
}
@Override
public TypedOutput toBody(Object object) {
return null;
}
// Custom method to convert stream from request to string
public static String fromStream(InputStream in) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder out = new StringBuilder();
String newLine = System.getProperty("\n");
String line;
while ((line = reader.readLine()) != null) {
out.append(line);
out.append(newLine);
}
return out.toString();
}
}
And it works perfectly! 而且效果很好!
For starters, your json is not json that Gson understand, so you can't use the Gson converter in Retrofit directly. 对于初学者,您的json并不是Gson可以理解的json,因此您不能直接在Retrofit中使用Gson转换器。 So
所以
public Observable<APIData> getdata ();
must be 一定是
public Observable<Response> getdata ();
Then, you have 那你有
adapter.create(WarehouseAPI.class).getdata()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.map((Response res) -> new BufferedStreamReader(res.body.body().bytesStream()))
.flatMap(stream -> {
return Observable.create(subscriber -> {
String line;
while((line = stream.readLine() != null) {
subscriber.onNext(gson.fromJson(line, APIData.class));
}
subscriber.onCompleted();
});
});
You can subscribe to that and receive each individual item of your json list. 您可以订阅它,并接收json列表中的每个项目。
This is not tested, and error cases are not handled (and validity of subscription is not tested, for shortness). 这未经测试,错误情况也未得到处理(为简短起见,未测试订阅的有效性)。
It should mostly be in the right direction though. 不过,它基本上应该朝着正确的方向发展。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.