jackson报错 Unrecognized field xxx

有个哥们写的比较清楚了,就直接转过来了,原文为:https://www.jianshu.com/p/785d7a043e4c
问题描述
使用Jackson的ObjectMapper将json字符串转换为对象时报错:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "sex" (class dev.wj.jacksonunrecognizedfielddemo.entity.User), not marked as ignorable (2 known properties: "name", "age"])
 at [Source: {"age":18, "name":"wj", "sex":1}; line: 1, column: 32] (through reference chain: dev.wj.jacksonunrecognizedfielddemo.entity.User["sex"])

问题分析
错误信息提示,未识别字段“sex”。
引起该问题的原因是在使用ObjectMapper将json字符串转换为对象时,被映射的对象中没有和json串中的字段对应。
举例
首先先建立User类,包含age和name两个字段。

public class User {

    private Integer age;

    private String name;

}

假设程序调用了别人的接口,返回一个描述user信息的json字符串:

  {
    "age": 18,
    "name": "wj",
    "sex": "男"
  }

该json串中包含了age、name、和sex三个字段。
此时如果将该字符串映射为User对象即会报出Unrecognized field xxx错误。

@RunWith(SpringRunner.class)
@SpringBootTest
public class JacksonTest {

    @Test
    public void jacksonTest() {

        String json = "{\"age\": 18, \"name\": \"wj\", \"sex\": \"男\"}";

        ObjectMapper objectMapper = new ObjectMapper();

        User user = null;
        try {
            user = objectMapper.readValue(json, User.class);
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println(user.toString());
    }
}

原因就是json串中的sex字段在User类中没有对应的字段映射。
解决方案
如果json中包含的字段都是有用的,那么映射类应包含所有json串中包含的字段。如在User类中添加private String sex字段即可。
如果json串中的字段不完全需要映射到实体类中,则可在实体类上加上@JsonIgnoreProperties(ignoreUnknown = true)注解,时jackson在转换时忽略不能映射的字段。

eclipse安装PMD,checkstyle,findbugs

PMD地址为:
https://dl.bintray.com/pmd/pmd-eclipse-plugin/updates/

checkstyle:
https://sourceforge.net/projects/eclipse-cs/
如果无法在线安装,可以下载zip包安装

findbugs:
http://findbugs.cs.umd.edu/eclipse/

rsync同步慢cpu占用高的问题

结合inotifywait和rsync做实时同步会遇到一些问题,会造成同步非常慢。常见的原因有如下:
1:inotifywait做实时监控,但是rsync是做全量同步
即inotifywait同步监控到文件变化,这个非常频繁,每触发一次rsync做了全量同步,inotifywait本来是能监控到具体的文件变化,所以本次只用同步这个变化的文件即可,而不是文件夹,即使是需要文件夹,去掉递归也行。
2:checksum带来的性能问题
如果每次修改文件大小会变化,可以去掉--checksum,有时候卡在sending incremental file list可能是因为这个原因导致的
3:频繁的触发了modify
modify会频繁的触发,如果在modify就同步可能会造成多次同步,解决方式是去掉modify事件,仅仅在关闭或者移动的时候触发rsync,可能的代码片段为:

if [[ $INO_EVENT =~ 'CLOSE_WRITE' ]] || [[ $INO_EVENT =~ 'MOVED_TO' ]] 

利用JDK内置资源获取全球国家ISO编码语言等资源

有时候需要在后台展示国家等信息,懒得去配置一个数据表专门存储这些信息,可采用如下代码:

import org.apache.commons.lang3.StringUtils;
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.locale.provider.ResourceBundleBasedAdapter;
import sun.util.resources.LocaleData;
import sun.util.resources.OpenListResourceBundle;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 获取JDK内置的一些资源数据
 */
public class DataResourceUtil {
    private static List<Country> countries;
    private static List<Currency> currencies;
    private static List<Language> languages;

    /**
     * 获取所有国家和对应的二字编码和三字编码
     *
     * @return
     */
    public static List<Country> getCountries() {
        if (countries != null) {
            return countries;
        }

        OpenListResourceBundle resource = getLocaleData().getLocaleNames(Locale.CHINA);
        synchronized (Country.class) {
            if (countries != null) {
                return countries;
            }
            Set<String> data = resource.keySet();
            List<String> twoCodes = data.stream()
                    .filter(code -> !StringUtils.isNumeric(code))
                    .filter(code -> StringUtils.isAllUpperCase(code))
                    .collect(Collectors.toList());
            twoCodes.sort(Comparator.naturalOrder());
            countries = twoCodes.stream().map(code -> {
                Locale locale = new Locale("", code);
                String threeCode = null;
                try {
                    threeCode = locale.getISO3Country();
                } catch (Exception e) {
                }
                return new Country(resource.getString(code), code, threeCode);
            }).collect(Collectors.toList());
            countries = Collections.unmodifiableList(countries);
            return countries;
        }
    }

    /**
     * 获取所有币种和对应的简码
     *
     * @return
     */
    public static List<Currency> getCurrencies() {
        if (currencies != null) {
            return currencies;
        }

        OpenListResourceBundle resource = getLocaleData().getCurrencyNames(Locale.CHINA);
        synchronized (Currency.class) {
            if (currencies != null) {
                return currencies;
            }
            Set<String> data = resource.keySet();
            List<String> codes = data.stream().filter(StringUtils::isAllLowerCase).collect(Collectors.toList());
            codes.sort(Comparator.naturalOrder());
            currencies = codes.stream().map(code -> new Currency(resource.getString(code), code.toUpperCase())).collect(Collectors.toList());
            currencies = Collections.unmodifiableList(currencies);
            return currencies;
        }
    }

    /**
     * 获取系统的语言
     *
     * @return
     */
    public static List<Language> getLanguages() {
        if (languages != null) {
            return languages;
        }

        Locale[] localeList = Locale.getAvailableLocales();
        synchronized (Language.class) {
            if (languages != null) {
                return languages;
            }
            languages = Arrays.stream(localeList).map(l -> {
                String iso3Country = null;
                try {
                    iso3Country = l.getISO3Country();
                } catch (MissingResourceException e) { }
                String language = l.getLanguage();
                String iso3Language = l.getISO3Language();
                String country = l.getCountry();
                String displayCountry = l.getDisplayCountry();
                String displayLanguage = l.getDisplayLanguage();
                String displayName = l.getDisplayName();
                if(StringUtils.isBlank( iso3Country)){
                    return null;
                }
                Country c = new Country(displayCountry, country, iso3Country);
                return new Language(displayLanguage, displayName, language, iso3Language, c);
            }).filter(Objects::nonNull).collect(Collectors.toList());

            languages = Collections.unmodifiableList(languages);
            return languages;
        }
    }

    public static void main(String[] args) {
//        List<Country> countries = getCountries();
//        countries.forEach(System.out::println);
//        List<Currency> currencies = getCurrencies();
//        currencies.forEach(System.out::println);
        List<Language> languages = getLanguages();
        languages.forEach(System.out::println);
    }

    private static LocaleData getLocaleData() {
        ResourceBundleBasedAdapter resource = ((ResourceBundleBasedAdapter) LocaleProviderAdapter.forJRE());
        return resource.getLocaleData();
    }


    public static class Country {
        // 国家名称
        private String name;
        // 二字编码
        private String twoCode;
        // 三字编码
        private String threeCode;

        private Country(String name, String twoCode, String threeCode) {
            this.name = name;
            this.twoCode = twoCode;
            this.threeCode = threeCode;
        }

        public String getName() {
            return name;
        }

        public String getTwoCode() {
            return twoCode;
        }

        public String getThreeCode() {
            return threeCode;
        }

        @Override
        public String toString() {
            return "Country{" +
                    "name='" + name + '\'' +
                    ", twoCode='" + twoCode + '\'' +
                    ", threeCode='" + threeCode + '\'' +
                    '}';
        }
    }

    public static class Currency {
        private String name;
        private String code;

        private Currency(String name, String code) {
            this.name = name;
            this.code = code;
        }

        public String getName() {
            return name;
        }

        public String getCode() {
            return code;
        }

        @Override
        public String toString() {
            return "Currency{" +
                    "name='" + name + '\'' +
                    ", code='" + code + '\'' +
                    '}';
        }
    }

    public static class Language {
        // 语言名称
        private String name;
        // 语言名称使用国家
        private String displayName;
        // 二字编码
        private String twoCode;
        // 三字编码
        private String threeCode;
        // 使用国家
        private Country country;

        public Language(String name, String displayName, String twoCode, String threeCode, Country country) {
            this.name = name;
            this.displayName = displayName;
            this.twoCode = twoCode;
            this.threeCode = threeCode;
            this.country = country;
        }

        public String getName() {
            return name;
        }

        public String getDisplayName() {
            return displayName;
        }

        public String getTwoCode() {
            return twoCode;
        }

        public String getThreeCode() {
            return threeCode;
        }

        public Country getCountry() {
            return country;
        }

        @Override
        public String toString() {
            return "Language{" +
                    "name='" + name + '\'' +
                    ", displayName='" + displayName + '\'' +
                    ", twoCode='" + twoCode + '\'' +
                    ", threeCode='" + threeCode + '\'' +
                    ", country=" + country +
                    '}';
        }
    }
}

代码转自:
https://gitee.com/lnkToKing/codes/eom09jrdp8ybf56nu423v77

echats自定义y轴百分比和tooltip图例

'tooltip':{
            formatter: function(params) {
          var result = ''
              params.forEach(function (item) {
                console.log(item)
                result += item.axisValue + "</br>" + item.marker +item.seriesName+":"+ item.data+"%"
              })
              return result
            },
            
            trigger:'axis'
          },
'yAxis': {
            'type': 'value',
            "scale":true,
            axisLabel: {
                formatter: '{value} %'
            }
          },