Jackson常用注解

序列化注解

@JsonAnyGetter

像普通属性一样序列化Map

public class ExtendableBean {
public String name;
private Map<String, String> properties; @JsonAnyGetter
public Map<String, String> getProperties() {
return properties;
}
}

序列化示例:

{
"name":"My bean",
"attr2":"val2",
"attr1":"val1"
}

@JsonGetter

将指定的方法标记为getter方法。可以用来代替@JsonProperty

public class MyBean {
public int id;
private String name; @JsonGetter("name")
public String getTheName() {
return name;
}
}

序列化示例:

{
"id": 1,
"name":"My bean"
}

@JsonPropertyOrder

用在类上,在序列化的时候自定义属性输出顺序

@JsonPropertyOrder({ "name", "id" })
public class MyBean {
public int id;
public String name;
}

序列化示例:

{
"name":"My bean",
"id": 1
}

@JsonRawValue

完全按照原样序列化属性的值

public class RawBean {
public String name; @JsonRawValue
public String json;
}

例如:

RawBean bean = new RawBean("My bean", "{\"attr\":false}");

将序列化为:

{
"name":"My bean",
"json":{
"attr":false
}
}

而不是:

{
"name":"My bean",
"json":"{\"attr\":false}"
}

@JsonValue

定义整个实体的序列化方法,Jackson将会使用该方法的输出作为序列化输出。

public enum TypeEnumWithValue {
TYPE1(1, "Type A"), TYPE2(2, "Type 2"); private Integer id;
private String name; // standard constructors @JsonValue
public String getName() {
return name;
}
}

序列化示例:

{
"name": "Type 2"
}

@JsonRootName

如果需要将实体包装一层,可以使用@JsonRootName来指定根包装器的名称

@JsonRootName(value = "user")
public class UserWithRoot {
public int id;
public String name;
}

序列化示例:

{
"user": {
"id": 1,
"name": "John"
}
}

如果不用该注解,将会序列化为:

{
"id": 1,
"name": "John"
}

@JsonSerialize

用于指定自定义序列化器来序列化实体

public class Event {
public String name; @JsonSerialize(using = CustomDateSerializer.class)
public Date eventDate;
}

自定义序列化器如下:

public class CustomDateSerializer extends StdSerializer<Date> {

    private static SimpleDateFormat formatter
= new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); public CustomDateSerializer() {
this(null);
} public CustomDateSerializer(Class<Date> t) {
super(t);
} @Override
public void serialize(
Date value, JsonGenerator gen, SerializerProvider arg2)
throws IOException, JsonProcessingException {
gen.writeString(formatter.format(value));
}
}

输出示例:

{
"name": "test",
"eventDate": "20-12-2014 02:30:00"
}

反序列化注解

@JsonCreator

指定反序列化使用的构造函数或方法

待反序列化Json示例:

{
"id":1,
"theName":"My bean"
}
public class BeanWithCreator {
public int id;
public String name; @JsonCreator
public BeanWithCreator(@JsonProperty("id") int id, @JsonProperty("theName") String name) {
this.id = id;
this.name = name;
}
}

@JacksonInject

指定某个字段从注入赋值,而不是从Json

public class BeanWithInject {
@JacksonInject
public int id; public String name;
}

示例用法:

String json = "{\"name\":\"My bean\"}";

InjectableValues inject = new InjectableValues.Std()
.addValue(int.class, 1);
BeanWithInject bean = new ObjectMapper().reader(inject)
.forType(BeanWithInject.class)
.readValue(json);

@JsonAnySetter

在反序列化时,将Map当成普通属性

待反序列化Json:

{
"name":"My bean",
"attr2":"val2",
"attr1":"val1"
}
public class ExtendableBean {
public String name;
private Map<String, String> properties; @JsonAnySetter
public void add(String key, String value) {
properties.put(key, value);
}
}

properties字段的值将会是由 attr2 -> val2,attr1 -> val1组成的键值对。

@JsonSetter

将方法标记为setter方法,可以指定属性名称

public class MyBean {
public int id;
private String name; @JsonSetter("name")
public void setTheName(String name) {
this.name = name;
}
}

@JsonDeserialize

用于指定自定义反序列化器来反序列化实体

public class Event {
public String name; @JsonDeserialize(using = CustomDateDeserializer.class)
public Date eventDate;
}

对应的反序列化器:

public class CustomDateDeserializer
extends StdDeserializer<Date> { private static SimpleDateFormat formatter
= new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); public CustomDateDeserializer() {
this(null);
} public CustomDateDeserializer(Class<?> vc) {
super(vc);
} @Override
public Date deserialize(
JsonParser jsonparser, DeserializationContext context)
throws IOException { String date = jsonparser.getText();
try {
return formatter.parse(date);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}

Jackson设置属性是否参与序列化

@JsonIgnoreProperties

在类上指定要忽略的属性

@JsonIgnoreProperties({ "id" })
public class BeanWithIgnore {
public int id;
public String name;
}

@JsonIgnore

在具体属性上忽略,使其不参与序列化过程

public class BeanWithIgnore {
@JsonIgnore
public int id; public String name;
}

@JsonIgnoreProperties是等效的。

@JsonIgnoreType

用在类上,将忽略该类所有属性

public class User {
public int id;
public Name name; @JsonIgnoreType
public static class Name {
public String firstName;
public String lastName;
}
}

@JsonInclude

用于排除值为empty/null/default的属性

@JsonInclude(Include.NON_NULL)
public class MyBean {
public int id;
public String name;
}

@JsonAutoDetect

强制序列化私有属性,不管它有没有getter方法

@JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class PrivateBean {
private int id;
private String name;
}

Jackson处理多态

一般都是组合起来使用,有下面三个注解:

  • @JsonTypeInfo

指定序列化中包含的类型信息的详细信息

  • @JsonSubTypes

指定带注释类型的子类型

  • @JsonTypeName

指定用于带注释的类的逻辑类型名称

public class Zoo {
public Animal animal; @JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = As.PROPERTY,
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Dog.class, name = "dog"),
@JsonSubTypes.Type(value = Cat.class, name = "cat")
})
public static class Animal {
public String name;
} @JsonTypeName("dog")
public static class Dog extends Animal {
public double barkVolume;
} @JsonTypeName("cat")
public static class Cat extends Animal {
boolean likesCream;
public int lives;
}
}

上述例子中,指定属性type为判断具体子类的依据,例如:type=dog,将被序列化为Dog类型。

Jackson通用注解(序列化反序列化都生效)

@JsonProperty

指定JSON中的属性名称

public class MyBean {
public int id;
private String name; @JsonProperty("name")
public void setTheName(String name) {
this.name = name;
} @JsonProperty("name")
public String getTheName() {
return name;
}
}

@JsonFormat

用于在序列化日期/时间值时指定格式。

public class Event {
public String name; @JsonFormat(
shape = JsonFormat.Shape.STRING,
pattern = "dd-MM-yyyy hh:mm:ss")
public Date eventDate;
}

@JsonUnwrapped

将对象中所有的属性与当前平级,不太好描述,简单说就是拆开包装。

public class UnwrappedUser {
public int id; @JsonUnwrapped
public Name name; public static class Name {
public String firstName;
public String lastName;
}
}

序列化示例:

{
"id":1,
"firstName":"John",
"lastName":"Doe"
}

如果不加@JsonUnwrapped注解,将被序列化为:

{
"id":1,
"name": {
"firstName":"John",
"lastName":"Doe"
}
}

@JsonView

指定视图,类似分组进行序列化/反序列化

定义视图:

public class Views {
public static class Public {}
public static class Internal extends Public {}
}

定义实体:

public class Item {
@JsonView(Views.Public.class)
public int id; @JsonView(Views.Public.class)
public String itemName; @JsonView(Views.Internal.class)
public String ownerName;
}

序列化示例:

String result = new ObjectMapper()
.writerWithView(Views.Public.class)
.writeValueAsString(item);

这时,将只会序列化iditemName字段

@JsonManagedReference, @JsonBackReference

@JsonManagedReference和@JsonBackReference注释用于处理父/子关系并解决循环问题。

例如,有两个相互引用的类:

public class ItemWithRef {
public int id;
public String itemName; @JsonManagedReference
public UserWithRef owner;
}
public class UserWithRef {
public int id;
public String name; @JsonBackReference
public List<ItemWithRef> userItems;
}

不加注解,会循环调用,导致内存溢出,这时候可以使用@JsonManagedReference@JsonBackReference来避免内存溢出。

@JsonIdentityInfo

用于指定在序列化/反序列化值时使用对象标识,例如,处理无限递归类型的问题。

@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class ItemWithIdentity {
public int id;
public String itemName;
public UserWithIdentity owner;
}

@JsonFilter

指定序列化期间要使用的过滤器。

@JsonFilter("myFilter")
public class BeanWithFilter {
public int id;
public String name;
}

示例代码:

BeanWithFilter bean = new BeanWithFilter(1, "My bean");

FilterProvider filters
= new SimpleFilterProvider().addFilter(
"myFilter",
SimpleBeanPropertyFilter.filterOutAllExcept("name")); String result = new ObjectMapper()
.writer(filters)
.writeValueAsString(bean);

自定义Jackson注解

可以使用@JacksonAnnotationsInside来开发自定义注解

@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonInclude(Include.NON_NULL)
@JsonPropertyOrder({ "name", "id", "dateCreated" })
public @interface CustomAnnotation {}

如何使用自定义注解:

@CustomAnnotation
public class BeanWithCustomAnnotation {
public int id;
public String name;
public Date dateCreated;
}

自定义注解可以增强代码复用,把一些通用的Jackson注解组合起来,形成一个新注解,新注解可以代替组合的注解。

Jackson MixIn 注解

动态地为某些类型增加统一的Jackson注解

实体:

public class Item {
public int id;
public String itemName;
public User owner;
}

MixIn类:

@JsonIgnoreType
public class MyMixInForIgnoreType {}

我们可以动态地让User类型不参与序列化:

Item item = new Item(1, "book", null);
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(User.class, MyMixInForIgnoreType.class);
result = mapper.writeValueAsString(item);

禁用Jackson注解

假设我们有一个带Jackson注解的实体:

@JsonInclude(Include.NON_NULL)
@JsonPropertyOrder({ "name", "id" })
public class MyBean {
public int id;
public String name;
}

我们可以这样来禁用该实体上的所有Jackson注解:

MyBean bean = new MyBean(1, null);
ObjectMapper mapper = new ObjectMapper();
mapper.disable(MapperFeature.USE_ANNOTATIONS);

Jackson的ObjectMapper用法

java类 转换为 json

可以直接序列化为Json字符串:

objectMapper.writeValueAsString(car);

或者,可以序列化到文件,文件内容是Json字符串:

objectMapper.writeValue(new File("target/car.json"), car);

json 转换为 java类

从字符串:

String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
objectMapper.readValue(json, Car.class);

从文件:

objectMapper.readValue(new File("target/json_car.json"), Car.class);

从URL:

objectMapper.readValue(new URL("target/json_car.json"), Car.class);

json转换为Jackson JsonNode

String json = "{ \"color\" : \"Black\", \"type\" : \"FIAT\" }";
JsonNode jsonNode = objectMapper.readTree(json);
String color = jsonNode.get("color").asText();
// Output: color -> Black

json 转换为 java集合

String jsonCarArray =
"[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
List<Car> listCar = objectMapper.readValue(jsonCarArray, new TypeReference<List<Car>>(){});

json 转换为 Map

String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
Map<String, Object> map = objectMapper.readValue(json, new TypeReference<Map<String,Object>>(){});

ObjectMapper的常用配置

忽略不识别的字段(json属性与目标实体存在属性上的差异):

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

允许原始值为null:

objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);

允许将枚举序列化/反序列化为数字:

objectMapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, false);

配置自定义序列化/反序列化器

假设有一个序列化器:

public class CustomCarSerializer extends StdSerializer<Car> {

    public CustomCarSerializer() {
this(null);
} public CustomCarSerializer(Class<Car> t) {
super(t);
} @Override
public void serialize(
Car car, JsonGenerator jsonGenerator, SerializerProvider serializer) {
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField("car_brand", car.getType());
jsonGenerator.writeEndObject();
}
}

一个反序列化器:

public class CustomCarDeserializer extends StdDeserializer<Car> {

    public CustomCarDeserializer() {
this(null);
} public CustomCarDeserializer(Class<?> vc) {
super(vc);
} @Override
public Car deserialize(JsonParser parser, DeserializationContext deserializer) {
Car car = new Car();
ObjectCodec codec = parser.getCodec();
JsonNode node = codec.readTree(parser); // try catch block
JsonNode colorNode = node.get("color");
String color = colorNode.asText();
car.setColor(color);
return car;
}
}

ObjectMapper使用他们:

//添加自定义序列化器
module.addSerializer(Car.class, new CustomCarSerializer());
//添加自定义反序列化器
module.addDeserializer(Car.class, new CustomCarDeserializer());

处理日期格式化

ObjectMapper objectMapper = new ObjectMapper();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z");
objectMapper.setDateFormat(df);

处理集合

反序列化为数组:

String jsonCarArray =
"[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true);
Car[] cars = objectMapper.readValue(jsonCarArray, Car[].class);

反序列化为集合:

String jsonCarArray =
"[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
ObjectMapper objectMapper = new ObjectMapper();
List<Car> listCar = objectMapper.readValue(jsonCarArray, new TypeReference<List<Car>>(){});

ObjectMapper的基本用法

ObjectMapper可以通过configure方法设置全局序列化/反序列化行为,例如:

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

常用的一些设置:

  1. DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES:忽略不识别的字段
  2. DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES:允许使用属性的默认值进行反序列化
  3. DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS:允许将枚举值序列化/反序列化为数字

注册自定义序列化/反序列化程序

//创建一个模块
SimpleModule module = new SimpleModule("CustomCarSerializer", new Version(1, 0, 0, null, null, null));
//将自定义序列化/反序列化程序注册到模块
module.addSerializer(Car.class, new CustomCarSerializer());
//module.addDeserializer(Car.class, new CustomCarDeserializer());
//注册模块
mapper.registerModule(module);

处理日期格式

DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z");
mapper.setDateFormat(df);

处理集合

处理数组

String jsonCarArray = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true);
Car[] cars = objectMapper.readValue(jsonCarArray, Car[].class);

处理集合

String jsonCarArray = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
ObjectMapper objectMapper = new ObjectMapper();
List<Car> listCar = objectMapper.readValue(jsonCarArray, new TypeReference<List<Car>>(){});

Jackson注解扩展

@JsonIdentityReference

使用指定的标识来序列化Java对象,而不是序列化整个对象

例如:

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
@JsonIdentityReference(alwaysAsId = true)
public class BeanWithoutIdentityReference {
private int id;
private String name;
}

将被序列化为:

1

@JsonAppend

运行在序列化时添加额外的属性

@JsonAppend(attrs = {
@JsonAppend.Attr(value = "version")
})
public class BeanWithAppend {
private int id;
private String name; // constructor, getters and setters
}

例如,我们在序列化时手动增加version = 1.0的属性

BeanWithAppend bean = new BeanWithAppend(2, "Bean With Append Annotation");
ObjectWriter writer = mapper.writerFor(BeanWithAppend.class).withAttribute("version", "1.0");
String jsonString = writer.writeValueAsString(bean);

序列化结果:

{
"id": 2,
"name": "Bean With Append Annotation",
"version": "1.0"
}

@JsonNaming

指定序列化的时候属性命名方式

有四种选项:

  • KEBAB_CASE

由连字符分割,例如:kebab-case

  • LOWER_CASE

所有的字母都转换为小写,例如:lowercase

  • SNAKE_CASE

所有的字母都转换为小写,并且由下划线分割,例如:snake_case

  • UPPER_CAMEL_CASE

所有名称元素,包括第一个元素,都以大写字母开头,后跟小写字母,并且没有分隔符,例如:UpperCamelCase

使用举例:

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public class NamingBean {
private int id;
private String beanName;
}

@JsonPropertyDescription

用于生成字段的描述信息

例如,有下面一个实体:

public class PropertyDescriptionBean {
private int id;
@JsonPropertyDescription("This is a description of the name property")
private String name;
}

我们可以输出该类的信息:

SchemaFactoryWrapper wrapper = new SchemaFactoryWrapper();
mapper.acceptJsonFormatVisitor(PropertyDescriptionBean.class, wrapper);
JsonSchema jsonSchema = wrapper.finalSchema();
String jsonString = mapper.writeValueAsString(jsonSchema);

结果如下:

{
"type": "object",
"id": "urn:jsonschema:com:baeldung:jackson:annotation:extra:PropertyDescriptionBean",
"properties":
{
"name":
{
"type": "string",
"description": "This is a description of the name property"
}, "id":
{
"type": "integer"
}
}
}

@JsonPOJOBuilder

自定义生成器类,来控制json的反序列化行为

@JsonPOJOBuilder有两个属性:

  • buildMethodName

将JSON字段绑定到bean的属性后,用于实例化预期bean的无参构造的名称。默认名称为build

  • withPrefix

用于自动检测JSON和bean属性之间匹配的名称前缀。默认前缀为with

假设我们要反序列化的json如下:

{
"id": 5,
"name": "POJO Builder Bean"
}

对应的pojo:

@JsonDeserialize(builder = BeanBuilder.class)
public class POJOBuilderBean {
private int identity;
private String beanName; // constructor, getters and setters
}

对应的生成器:

@JsonPOJOBuilder(buildMethodName = "createBean", withPrefix = "construct")
public class BeanBuilder {
private int idValue;
private String nameValue; public BeanBuilder constructId(int id) {
idValue = id;
return this;
} public BeanBuilder constructName(String name) {
nameValue = name;
return this;
} public POJOBuilderBean createBean() {
return new POJOBuilderBean(idValue, nameValue);
}
}

使用ObjectMapper反序列化:

String jsonString = "{\"id\":5,\"name\":\"POJO Builder Bean\"}";
POJOBuilderBean bean = mapper.readValue(jsonString, POJOBuilderBean.class);

Jackson使用指南的更多相关文章

  1. Jackson 工具类使用及配置指南

    目录 前言 Jackson使用工具类 Jackson配置属性 Jackson解析JSON数据 Jackson序列化Java对象 前言 Json数据格式这两年发展的很快,其声称相对XML格式有很对好处: ...

  2. Jackson工具类使用及配置指南、高性能配置(转)

    Jackson使用工具类 通常,我们对JSON格式的数据,只会进行解析和封装两种,也就是JSON字符串--->Java对象以及Java对象--->JSON字符串. public class ...

  3. Retrofit结合RxJava使用指南

    Retrofit结合RxJava使用指南 Retrofit是一个当前很流行的网络请求库, 官网的介绍是: "Type-safe HTTP client for Android and Jav ...

  4. [翻译]Java日志终极指南

    本文由 ImportNew - Wing 翻译自 loggly.欢迎加入翻译小组.转载请见文末要求. Java日志基础 Java使用了一种自定义的.可扩展的方法来输出日志.虽然Java通过java.u ...

  5. web之困:现代web应用安全指南

    <web之困:现代web应用安全指南>在web安全领域有“圣经”的美誉,在世界范围内被安全工作者和web从业人员广为称道,由来自google chrome浏览器团队的世界顶级黑客.国际一流 ...

  6. Android最佳实践指南

    Updated on 2016/1/6 修正了一些翻译段落欢迎转载,但请保留译者链接:http://www.jianshu.com/p/613d28a3c8a0 Lessons learned fro ...

  7. Java日志终极指南

    Java日志基础 Java使用了一种自定义的.可扩展的方法来输出日志.虽然Java通过java.util.logging包提供了一套基本的日志处理API,但你可以很轻松的使用一种或者多种其它日志解决方 ...

  8. 分布式消息系统Jafka入门指南之二

    分布式消息系统Jafka入门指南之二 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs 三.Jafka的文件夹结构 1.安装tree命令 $ sudo yu ...

  9. spring 4 升级踩雷指南

    spring 4 升级踩雷指南 前言 最近,一直在为公司老项目做核心库升级工作.本来只是想升级一下 JDK8 ,却因为兼容性问题而不得不升级一些其他的库,而其他库本身依赖的一些库可能也要同步升级.这是 ...

随机推荐

  1. [Python源码剖析]获取Python小整数集合范围

    #!/usr/bin/env python #-*- coding=utf-8 -*- small_ints = dict() for i in range(-10000,10000): small_ ...

  2. WeChall_Prime Factory (Training, Math)

    Your task is simple:Find the first two primes above 1 million, whose separate digit sums are also pr ...

  3. 在form子句中使用子查询时的注意事项

    今天中午为了弄清这个问题,本人真的是头都搞大了!最后明白了一点,在from子句中使用子查询是,一定要将临时表的别名带上,否则会灰常痛苦!!!

  4. 【redis】-- redis的持久化(作为数据库)

    目录 1.RDB rdb持久化的方式 rdb方式的优点: aof的优点 3.持久化的其他特性 日志重写 工作原理 rdb和aof混合使用 redis是一个基于内存的数据库,故在redis正在运行的数据 ...

  5. [REDIS 读书笔记]第一部分 数据结构与对象 跳跃表

    下面是跳跃表的基本原理,REDIS的实现大致相同 跳跃表的一个特点是,插入NODE是通过随机的方式来决定level的,比较奇特 下面是skipList的一个介绍,转载来的,源地址:http://ken ...

  6. Kvm 简介 安装 使用 桥接网络

    KVM 全称是 基于内核的虚拟机(Kernel-based Virtual Machine),它是一个 Linux 的一个内核模块,该内核模块使得 Linux 变成了一个 Hypervisor: 它由 ...

  7. python网络爬虫(二)requests库的基本介绍和使用

    一.requests库的七个重要方法 (1)最常用方法:requests.get(url,params=None,**kwargs)//对应HTTP协议的GET()操作 (请求获得URL位置的资源) ...

  8. CentOS7 GlusterFS文件系统部署

    一.GlusterFS简介 GlusterFS(GNU ClusterFile System)是一种全对称的开源分布式文件系统,所谓全对称是指GlusterFS采用弹性哈希算法,没有中心节点,所有节点 ...

  9. Mac下搭建selenium环境

    1,安装selenium 打开terminal,使用以下命令安装selenium:   pip install -U selenium 2,下载chromedriver,并放在python的安装根目录 ...

  10. 6.python设置代理和添加镜像源介绍

    为什么要修改镜像源? 一般使用python安装库,会用到pip install xxx 指令或者conda install xxx指令,因为pip和conda默认国外镜像源,这时会在Python的官方 ...