题目分析

  • 使用装饰器模式,继承自IO接口,来自定义一个输入输出流,以实现给某个类动态的添加功能
  • 对于输入流,继承自FilterInputStream,可以从文件中读取并解析JSON字符串,也可以从URL中请求JSON。
  • 对于输出流,继承自FilterOutputStream,可以把对象序列化为JSON字符串并写入文件
  • 这里就是运用了装饰模式,给原本没有功能的IO接口动态的添加了可以解析JSON的功能

UML图

代码

JSON字符串对应的实体类
/** * @ClassName: Data * @Author: Leo * @Description: * @Date: 2019/5/30 20:13 */
@lombok.Data
@AllArgsConstructor
@NoArgsConstructor
public class Data {
    private String icon;
    private int id;
    private String link;
    private String name;
    private int order;
    private int visible;

    @Override
    public String toString() {
        return "Data{" +
                "icon='" + icon + '\'' +
                ", id=" + id +
                ", link='" + link + '\'' +
                ", name='" + name + '\'' +
                ", order=" + order +
                ", visible=" + visible +
                '}' + "\n";
    }
}

/** * @ClassName: Link * @Author: Leo * @Description: * @Date: 2019/5/30 20:13 */
@lombok.Data
@AllArgsConstructor
@NoArgsConstructor
public class Link {
    private List<Data> data;
    @JsonProperty("errorCode")
    private int errorcode;
    @JsonProperty("errorMsg")
    private String errormsg;

    @Override
    public String toString() {
        return "Link{" +
                "data=" + data +
                ", errorcode=" + errorcode +
                ", errormsg='" + errormsg + '\'' +
                '}';
    }
}

自定义的装饰器流,可以多种方式解析JSON及序列化JSON对象
JSONInputStream
/** * @ClassName: JSONInputStream * @Author: Leo * @Description: 自定义的JSON工具流类 能以多种方式解析JSON并反序列化 * @Date: 2019/5/30 15:14 */
public class JSONInputStream extends FilterInputStream {


    public JSONInputStream(InputStream in) {
        super(in);
    }

    /** * 从文件中读取JSON字符串 并反序列化为bean对象 * * @param cla bean对象对应的字节码 * @return */
    public Object read(Class cla) throws IOException {
        return new ObjectMapper().readValue(in, cla);
    }

    /** * 根据URL请求JSON 并反序列化为bean对象 * * @param url 请求的URL * @param cla bean对象对应的字节码 */
    public Object read(String url, Class cla) throws IOException {
        String jsonStr = new OkHttpClient()
                .newCall(new Request
                        .Builder()
                        .url(url)
                        .get()
                        .build())
                .execute()
                .body()
                .string();
        return new ObjectMapper().readValue(jsonStr, cla);
    }

    @Override
    public int read() throws IOException {
        return 0;
    }
}


JSONOutputStream
/** * @ClassName: JSONOutputStream * @Author: Leo * @Description: 可以将对象序列化为JSON字符串并写入文件中 * @Date: 2019/5/30 15:14 */
public class JSONOutputStream extends FilterOutputStream {

    public JSONOutputStream(@NotNull OutputStream out) {
        super(out);
    }

    /** * 把对象序列化为JSON格式 并写入到文件中 * * @param object */
    public void write(Object object) throws IOException {
        new ObjectMapper().writeValue(out, object);
    }

    @Override
    public void write(int b) throws IOException {

    }
}

测试类

/** * @Author:Leo-GH * @Date: 2019/5/30 15:05 **/
public class Main {
    private static final String URL = "https://www.wanandroid.com/friend/json";

    public static void main(String[] args) throws IOException {
    	//测试输入
        JSONInputStream jsonInputStream = new JSONInputStream(new FileInputStream(new File("F://info.json")));
        Link link = (Link) jsonInputStream.read(Link.class);
        System.out.println(link);
        //测试输出
        JSONOutputStream jsonOutputStream = new JSONOutputStream(new FileOutputStream(new File("F://info.txt")));
        jsonOutputStream.write(link);

    }
}

总结:

JSON格式:

  1. 该模式的优缺点,特别从开闭原则论述
  • 可以给一个现有的对象添加新的功能,同时又不改变其结构,相比于继承来说更加灵活
  • 把职责分配给单一的类,如果想给某个类添加职责,直接去装饰就可以,这样就避免了某个类的功能太多
  1. 编程中遇到的问题及解决方法
  • 解析JSON使用了Jackson框架