1

I am trying to parse through a nested JSON object to retrieve the value of the key "routing_bic". For some reason, it works with sample2.xml (i.e. "From main: 103"), but doesn't work with sample1.xml (i.e. "From main: 0").

In both cases, the ("From loop: 103") is always present which brings me to the question of why I am unable to output it in the "From main: " even though it is correctly being captured in the loop itself.

package com.project.microserviceB;

import java.io.BufferedReader;
import java.io.FileReader;

import java.util.Iterator;

import org.json.JSONArray;
import org.json.JSONObject;
import org.json.XML;

public class Tesst {
    
    static String line = "", str = "";
    
    public static void main(String[] args) throws Exception {

        String filepath = "C:/Users/Navi/Downloads/sample1.xml";
        
        try ( BufferedReader br = new BufferedReader(new FileReader(filepath)); ) {
            while ((line = br.readLine()) != null) {
                str += line;
            }
        }

        JSONObject jsondata = XML.toJSONObject(str);
        
        System.out.println("From main: " + getValueFromKey(jsondata, "routing_bic"));
    }

    private static Integer getValueFromKey(JSONObject json, String key) {
        boolean exists = json.has(key);
        Iterator<?> keys;
        String nextKeys;
        Integer foundKey = 0;

        if(!exists) {
            keys = json.keys();
            while (keys.hasNext()) {
                // Store next Key in nextKeys
                nextKeys = (String)keys.next();
                
                try {
                    // Check if the given Key is a JSON Object
                    if(json.get(nextKeys) instanceof JSONObject) {
                        // If Key does not exist
                        if(!exists) {
                            // Recursive function call
                            foundKey = getValueFromKey(json.getJSONObject(nextKeys), key);
                        }
                    } else if (json.get(nextKeys) instanceof JSONArray) {
                        JSONArray jsonArray = json.getJSONArray(nextKeys);
                        for(int i = 0; i < jsonArray.length(); i++) {
                            String jsonArrayString = jsonArray.get(i).toString();
                            JSONObject innerJsonObject = new JSONObject(jsonArrayString);
                            
                            // Recursive function call
                            if(!exists) {
                                foundKey = getValueFromKey(innerJsonObject.getJSONObject(nextKeys), key);
                            }
                        }
                    }
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        } else {
            // If key exists, print value
            foundKey = parseObject(json, key);
            System.out.println("From loop: " + foundKey);
        }
//      System.out.println("Found Key = " + foundKey);
        return foundKey;
    }
    
    private static Integer parseObject(JSONObject json, String key) {
        System.out.println("From parseObject = " + json.get(key));
        return json.getInt(key);
    }
    
}

Sample1.xml

<Test>
    <BIBRq>
        <UserId>123</UserId>
        <CIFNo>123</CIFNo>
        <CompanyId>asd</CompanyId>
        <LegalId>123</LegalId>
        <LegalIdType>ABC</LegalIdType>
        <LegalIdCountry>ABC</LegalIdCountry>
    </BIBRq>
    <SubSvcRq>
        <SubSvc>
            <SubSvcRqHeader>
                <SvcCode>ABCD</SvcCode>
                <SubSvcSeq>1</SubSvcSeq>
                <TxnRef>12345</TxnRef>
                <ClientUserID/>
            </SubSvcRqHeader>
            <SubSvcRqDetail>
                <ft_tnx_record>
                    <additional_field>
                        <account_details>
                            <routing_bic>103</routing_bic>
                        </account_details>
                    </additional_field>
                </ft_tnx_record>
            </SubSvcRqDetail>
        </SubSvc>
    </SubSvcRq>
</Test>

Sample1.xml output (wrong)

From parseObject = 103
From loop: 103
From main: 0

Sample2.xml

<Test>
    <SubSvcRq>
        <SubSvc>
            <SubSvcRqHeader>
                <SvcCode>ABCD</SvcCode>
                <SubSvcSeq>1</SubSvcSeq>
                <TxnRef>12345</TxnRef>
                <ClientUserID/>
            </SubSvcRqHeader>
            <SubSvcRqDetail>
                <ft_tnx_record>
                    <additional_field>
                        <account_details>
                            <routing_bic>103</routing_bic>
                        </account_details>
                    </additional_field>
                </ft_tnx_record>
            </SubSvcRqDetail>
        </SubSvc>
    </SubSvcRq>
</Test>

Sample2.xml output (correct)

From parseObject = 103
From loop: 103
From main: 103

2
  • 1
    Are you willing to accept an alternative solution? Commented May 17, 2021 at 14:55
  • @BuildSlayer yes go ahead :). As long as I am able to get the "103" out. Commented May 17, 2021 at 15:30

1 Answer 1

2

I was taught not to debug recursions by my lecturer. Fortunately, I understood your idea and implemented it.

Think simple - imagine you are a node in the JSON:

  • If you are a JSONObject:
    • If you have the key - return the value.
    • If one of your children has it (recursion) - return it, else return null
  • If you are a JSONArray, return if one of your elements has the value (recursion)
  • You are not a JSONObject and not a JSONArray, return null.

Now it's easy to implement:

private static Integer getValueFromKey2(Object object, String key) {
    if (object instanceof JSONObject) {
        JSONObject jsonObject = (JSONObject) object;

        if (jsonObject.has(key)) {
            return jsonObject.getInt(key);
        }

        return jsonObject.keySet().stream()
                .map(childKey -> getValueFromKey2(jsonObject.get(childKey), key))
                .filter(Objects::nonNull)
                .findFirst()
                .orElse(null);
    } else if (object instanceof JSONArray) {
        JSONArray jsonArray = (JSONArray) object;

        return IntStream.range(0, jsonArray.length())
                .mapToObj(jsonArray::get)
                .map(o -> getValueFromKey2(o , key))
                .filter(Objects::nonNull)
                .findFirst()
                .orElse(null);
    } else {
        return null;
    }
}

Output:

From main: 103
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for explaining it! I am still very new to Java, hence I'll take the time to understand your .mapToObj and .map. Apart from that, thank you for your answer. Gladly appreciate you taking the time to help out :).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.