Используйте команду xticks .
import matplotlib.pyplot as plt
t11 = ['00', '01', '02', '03', '04', '05', '10', '11', '12', '13', '14', '15',
'20', '21', '22', '23', '24', '25', '30', '31', '32', '33', '34', '35',
'40', '41', '42', '43', '44', '45', '50', '51', '52', '53', '54', '55']
t12 = [173, 135, 141, 148, 140, 149, 152, 178, 135, 96, 109, 164, 137, 152,
172, 149, 93, 78, 116, 81, 149, 202, 172, 99, 134, 85, 104, 172, 177,
150, 130, 131, 111, 99, 143, 194]
plt.bar(range(len(t12)), t12, align='center')
plt.xticks(range(len(t12)), t11, size='small')
plt.show()
Обычно реализации коллекции «берут» тип из объявления поля коллекции, а не из данного элемента в List
/ Set
/ и т. Д. Нам нужно написать собственный сериализатор, который для каждого элемента находит сериализатор и использует его. Простая реализация:
class TypeAwareListJsonSeserializer implements JsonSerializer<List<?>> {
@Override
public JsonElement serialize(List<?> src, Type typeOfSrc, JsonSerializationContext context) {
if (src == null) {
return JsonNull.INSTANCE;
}
JsonArray array = new JsonArray();
for (Object item : src) {
JsonElement jsonElement = context.serialize(item, item.getClass());
array.add(jsonElement);
}
return array;
}
}
И вот как мы можем использовать это:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.annotations.JsonAdapter;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
public class GsonApp {
public static void main(String[] args) throws Exception {
List<BaseBean> children = Arrays.asList(new BaseBean(), new ChildBean(), new ChildBean2());
BaseBeanHolder baseHolder = new BaseBeanHolder(children);
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.create();
System.out.println(gson.toJson(baseHolder));
}
}
class BaseBean {
String baseField = "base";
}
class ChildBean extends BaseBean {
String childField = "child";
}
class ChildBean2 extends BaseBean {
int bean2Int = 356;
}
class BaseBeanHolder {
@JsonAdapter(TypeAwareListJsonSeserializer.class)
private List<? extends BaseBean> beans;
// getters, setters, toString
}
Выше кода печатается:
{
"beans": [
{
"baseField": "base"
},
{
"childField": "child",
"baseField": "base"
},
{
"bean2Int": 356,
"baseField": "base"
}
]
}
Во время сериализации мы теряем информацию о типе, которая потребуется в процессе десериализации. Я разработал информацию простого типа, которая будет храниться во время сериализации и использоваться при десериализации. Это может выглядеть следующим образом:
class TypeAwareListJsonAdapter implements JsonSerializer<List<?>>, JsonDeserializer<List<?>> {
private final String typeProperty = "@type";
@Override
public JsonElement serialize(List<?> src, Type typeOfSrc, JsonSerializationContext context) {
if (src == null) {
return JsonNull.INSTANCE;
}
JsonArray array = new JsonArray();
for (Object item : src) {
JsonObject jsonElement = (JsonObject) context.serialize(item, item.getClass());
jsonElement.addProperty(typeProperty, item.getClass().getSimpleName());
array.add(jsonElement);
}
return array;
}
@Override
public List<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
final Type elementType = $Gson$Types.getCollectionElementType(typeOfT, List.class);
if (json instanceof JsonArray) {
final JsonArray array = (JsonArray) json;
final int size = array.size();
if (size == 0) {
return Collections.emptyList();
}
final List<?> suites = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
JsonObject jsonElement = (JsonObject) array.get(i);
String simpleName = jsonElement.get(typeProperty).getAsString();
suites.add(context.deserialize(jsonElement, getClass(simpleName, elementType)));
}
return suites;
}
return Collections.emptyList();
}
private Type getClass(String simpleName, Type defaultType) {
try {
// you can use mapping or something else...
return Class.forName("com.model." + simpleName);
} catch (ClassNotFoundException e) {
return defaultType;
}
}
}
Самая большая проблема заключается в том, как сопоставить классы значениям JSON
. Мы можем использовать простое имя класса или предоставить Map<String, Class>
и использовать его. Теперь мы можем использовать его, как указано выше. Пример приложения печатается сейчас:
{
"beans": [
{
"baseField": "base",
"@type": "BaseBean"
},
{
"childField": "child",
"baseField": "base",
"@type": "ChildBean"
},
{
"bean2Int": 356,
"baseField": "base",
"@type": "ChildBean2"
}
]
}
BaseBean{baseField='base'}
ChildBean{baseField='base', childField='child'}
ChildBean2{baseField='base', bean2Int=356}
Еще одно дополнение: я только что подумал, что по крайней мере сериализация отлично работает с массивами , поэтому простым обходным решением было переделать держатель:
static class BaseBeanHolder {
BaseBean[] beans;
public BaseBeanHolder(BaseBean... beans) { this.beans = beans; }
}
Gson построен с учетом «Я собираюсь быть использован для сериализации» и «Я собираюсь быть использован для десериализации».
Нет никакого способа определить из необработанного JSON, каков точный тип времени выполнения потомка из BaseBean
.
Вы можете использовать RuntimeTypeAdapterFactory
, как описано здесь , здесь - к сожалению, он не публикуется с базовым модулем Gson и не находится в Maven Central, как описано здесь . Это опубликует достаточно информации с JSON, что позволит Gson десериализовать его.