JavaでJSON文字列から派生HashMapを平らに

Simplexity:

私は様々な理由によって、私は、JavaとAndroidのスタジオでフェイブルF#からJSONオブジェクトをデシリアライズする必要がある状況で終わっています。次のように文字列は次のとおりです。

{"MainForm":{"OriginMerd":{"id":"onMggagerd","number":5,"tests":{"Blod":{"blodid":"1","glucose":52}}}}}

コード:

    Stream<Map.Entry<String, String>> flatten(Map<String, Object> map) 
    {
        return map.entrySet()
                .stream()
                .flatMap(this::extractValue);
    }

    Stream<Map.Entry<String, String>> extractValue(Map.Entry<String, Object> entry) {
        if (entry.getValue() instanceof String) {
            return Stream.of(new AbstractMap.SimpleEntry(entry.getKey(), (String) entry.getValue()));
        } else if (entry.getValue() instanceof Map) {
            return flatten((Map<String, Object>) entry.getValue());
        }
        return null;
    }

    @ReactMethod
    public void testFunc(String jsonString, Callback cb){
        Map<String,Object> map = new HashMap<>();

        ObjectMapper mapper = new ObjectMapper();

        try {
            //convert JSON string to Map
            map = mapper.readValue(String.valueOf(jsonString), new TypeReference<Map<String, Object>>() {
            });


            Map<String, String> flattenedMap = flatten(map)
                     .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

            for (Map.Entry<String, String> entry : flattenedMap.entrySet()) {
                Log.e("flatmap",entry.getKey() + "/" + entry.getValue());

                //System.out.println(entry.getKey() + "/" + entry.getValue());
            }
        } catch (JsonParseException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        Log.e("JSONSTRING", jsonString);

        cb.invoke("OK");
    }

まず、私はそのような私が、私はこのアプローチに続くのマップを取得するために、オブジェクトマッパーを使用して、私はオブジェクトマッパーでマップにそれを作ると思います考え出しHashMapを平らにするためにどのように?

しかし、これで問題は結果は私だけorginMerd IDとblodid、ない数またはグルコースのフィールドを与えることです。これを達成するためのエレガントな方法はありますか?私は残念ながら非常によくジャワに精通しておりません。

davidxxx:

あなたはJSONの文字列型やマップの値のためだけのケースを処理します。

if (entry.getValue() instanceof String) {
    return Stream.of(new AbstractMap.SimpleEntry(entry.getKey(), (String) entry.getValue()));
} else if (entry.getValue() instanceof Map) {
    return flatten((Map<String, Object>) entry.getValue());
}

番号またはグルコースのエントリを取得するには、あなたも処理するNumberタイプを持つLongか、IntegerあなたはJSONデシリアライゼーションから何を得るによります。

このアプローチの問題点は、ということであるIntegerLongされないStringと、実際にあなたがJSONエントリをマッピングStream<Map.Entry<String, String>>
数字を置くString変数はで可能ですtoString()

例えば、数値と文字列の両方を処理します:

final String value = entry.getValue();
if (value instanceof String || value instanceof Number) {
    return Stream.of(new AbstractMap.SimpleEntry(entry.getKey(),
                                                value.toString()));
}
else if (value instanceof Map) {
    return flatten((Map<String, Object>) value);
}
// you may return null but you will at least log something
else {
     LOGGER.warn("field with key {} and value {} not mapped", entry.getKey(), value);
     return null;
}

しかし、それはまた、それを使用する前に、いくつかのチェックを必要とする、あなたの地図の内容が不明確になります。
以下のように同様にジェネリック型を使用してStream<Map.Entry<String, Object>>、同様の問題を作成します。

私はあなたのモデルを表すとデシリアライズの間にそれを使用するために、特定のクラスを使用することを検討できると考えるようにします。

Foo foo = mapper.readValue(String.valueOf(jsonString), Foo.class);

ここで、Foo期待された構造を記述するクラスです。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=228308&siteId=1