নাম-মান সংগ্রহের জন্য একটি ইউআরআই স্ট্রিং পার্স করুন


273

আমি এর মতো ইউআরআই পেয়েছি:

https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback

পার্সেড উপাদানগুলির সাথে আমার একটি সংগ্রহ দরকার:

NAME               VALUE
------------------------
client_id          SS
response_type      code
scope              N_FULL
access_type        offline
redirect_uri       http://localhost/Callback

নির্ভুলভাবে বলতে গেলে , আমার কাছে সি # /। নেট এইচটিপি ইউটিলিটি P পার্সেকুয়ারি স্ট্রিংয়ের জন্য জাভা সমতুল্য দরকার পদ্ধতির ।

দয়া করে আমাকে এ সম্পর্কে একটি পরামর্শ দিন।

ধন্যবাদ।



@ ম্যাটবাল যদি ওপি অ্যান্ড্রয়েড ব্যবহার করে তবে তা হ'ল
হুয়ান মেন্ডিস

156
এটি কি মাইন্ড-বগলিং নয় যে এটি java.net.URI/ এর মূল API এর অংশ নয় java.net.URL?
দিলুম রানাতুঙ্গা

: কঠিন গ্রন্থাগার এবং কাজ উদাহরণস্বরূপ উভয় ব্যকরণগত ও ফর্ম্যাট অপারেশনের জন্য - এই সমাধান দয়া করে চেক করুন stackoverflow.com/a/37744000/1882064
arcseldon

উত্তর:


341

আপনি যদি কোনও বাহ্যিক গ্রন্থাগার না ব্যবহার করে এটি অর্জনের কোনও উপায় সন্ধান করে থাকেন তবে নীচের কোডটি আপনাকে সহায়তা করবে।

public static Map<String, String> splitQuery(URL url) throws UnsupportedEncodingException {
    Map<String, String> query_pairs = new LinkedHashMap<String, String>();
    String query = url.getQuery();
    String[] pairs = query.split("&");
    for (String pair : pairs) {
        int idx = pair.indexOf("=");
        query_pairs.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"), URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
    }
    return query_pairs;
}

<map>.get("client_id")আপনার প্রশ্নের উত্তর দেওয়া URL সহ আপনি ফিরে মানচিত্রে অ্যাক্সেস করতে পারবেন এটি "এসএস" ফিরে আসবে।

আপডেট আপডেট URL- ডিকোডিং

আপডেট এই উত্তরটি এখনও বেশ জনপ্রিয়, আমি উপরের পদ্ধতির একটি উন্নত সংস্করণ তৈরি করেছি, যা একই কী এবং পরামিতিগুলির সাথে কোনও মূল্য ছাড়াই পরিচালনা করে।

public static Map<String, List<String>> splitQuery(URL url) throws UnsupportedEncodingException {
  final Map<String, List<String>> query_pairs = new LinkedHashMap<String, List<String>>();
  final String[] pairs = url.getQuery().split("&");
  for (String pair : pairs) {
    final int idx = pair.indexOf("=");
    final String key = idx > 0 ? URLDecoder.decode(pair.substring(0, idx), "UTF-8") : pair;
    if (!query_pairs.containsKey(key)) {
      query_pairs.put(key, new LinkedList<String>());
    }
    final String value = idx > 0 && pair.length() > idx + 1 ? URLDecoder.decode(pair.substring(idx + 1), "UTF-8") : null;
    query_pairs.get(key).add(value);
  }
  return query_pairs;
}

জাভা 8 সংস্করণ আপডেট করুন

public Map<String, List<String>> splitQuery(URL url) {
    if (Strings.isNullOrEmpty(url.getQuery())) {
        return Collections.emptyMap();
    }
    return Arrays.stream(url.getQuery().split("&"))
            .map(this::splitQueryParameter)
            .collect(Collectors.groupingBy(SimpleImmutableEntry::getKey, LinkedHashMap::new, mapping(Map.Entry::getValue, toList())));
}

public SimpleImmutableEntry<String, String> splitQueryParameter(String it) {
    final int idx = it.indexOf("=");
    final String key = idx > 0 ? it.substring(0, idx) : it;
    final String value = idx > 0 && it.length() > idx + 1 ? it.substring(idx + 1) : null;
    return new SimpleImmutableEntry<>(key, value);
}

ইউআরএল দিয়ে উপরের পদ্ধতিটি চালানো

https://stackoverflow.com?param1=value1&param2=&param3=value3&param3

এই মানচিত্রটি ফেরত দেয়:

{param1=["value1"], param2=[null], param3=["value3", null]}

13
আপনি নাম এবং প্যারামিটারগুলি ডিকোড করতে ভুলে যাচ্ছেন, কারণ সাধারণত লাইব্রেরিগুলিকে সাধারণ কাজ করতে দেওয়া ভাল one
জুয়ান মেন্ডেস

10
প্রকৃতপক্ষে, আপনি ঠিক বলেছেন ... তবে আমি ব্যক্তিগতভাবে নিজের দ্বারা এই জাতীয় "সহজ" কাজগুলি লেখার চেয়ে আমার নিজের প্রতিটি কাজটির জন্য নিজস্ব লাইব্রেরি ব্যবহার না করেই পছন্দ করি।
Pr0gr4mm3r

2
যদি আপনার একই নাম / কী সহ একাধিক পরামিতি থাকে তবে এই ফাংশনটি ব্যবহার করে অনুরূপ কীটি মানটিকে ওভাররাইড করবে।
স্নোবল 147

4
@ ক্রিস আপনি এক্সএমএল / এইচটিএমএলকে ইউআরএল এনকোডিং দিয়ে পালিয়ে বেড়াচ্ছেন। আপনার উদাহরণ ইউআরএল হওয়া উচিত: a.com/q?1=a%26b&2=b%26c

3
কোন ফাংশনগুলি ব্যবহৃত হয় তা
বোঝানো ভাল লাগবে

311

org.apache.http.client.utils.URLEncodedUtils

এটি একটি সুপরিচিত গ্রন্থাগার যা এটি আপনার জন্য করতে পারে

import org.apache.hc.client5.http.utils.URLEncodedUtils

String url = "http://www.example.com/something.html?one=1&two=2&three=3&three=3a";

List<NameValuePair> params = URLEncodedUtils.parse(new URI(url), Charset.forName("UTF-8"));

for (NameValuePair param : params) {
  System.out.println(param.getName() + " : " + param.getValue());
}

আউটপুট

one : 1
two : 2
three : 3
three : 3a

আমি সমস্ত উপাদানগুলি পাস না করে এর নাম দিয়ে মানটি পেতে পারি? আমি এর অর্থ কিছু বলতে চাই: System.out.print (params ["one"]]);
সের্গেই শাফিয়েভ

3
@SergeyShafiev এটা একটা রূপান্তর করতে তুচ্ছ হয় List<NameValuePair>একটি মধ্যে Map<String,String>জাভা হ্যাশ মানচিত্রের জন্য বন্ধনী এক্সেস আছে না, এটি দেখতে কেমন হবে map.get("one")আপনি যে কাজ করতে কিভাবে জানি না, এটা অন্য প্রশ্ন হওয়া উচিত (কিন্তু আপনার নিজের প্রথম তে এটি চেষ্টা করুন) । আমরা এখানে SO
জুয়ান মেন্ডেস

6
আপনার ইউআরএলটিতে যদি দ্বিগুণ একই প্যারামিটার থাকে তবে সতর্কতা অবলম্বন করুন (যেমন? A = 1 এবং a = 2) ইউআরএলএনকোডযুক্ত ইউটিলেসগুলি একটি অবৈধআর্গুমেন্ট এক্সেক্সশন ফেলে দেবে
ক্রিস্টার্ক

10
@ ক্রাইস্টार्क httpclient 4.3.3 অনুসারে, সদৃশ নামগুলির সাথে ক্যোয়ারী স্ট্রিং কোনও ব্যতিক্রম ছুঁড়ে না। এটি প্রত্যাশার মতো কাজ করে। [foo = বার, foo = বাজ]System.out.println(URLEncodedUtils.parse(new URI("http://example.com/?foo=bar&foo=baz"), "UTF-8")); মুদ্রণ করবে ।
আকিহিরো হারাই

4
অ্যান্ড্রয়েড 6 হিসাবে, অ্যাপাচি এইচটিটিপি ক্লায়েন্ট লাইব্রেরি সরানো হয়েছে। এর অর্থ URLEncodedUtils and নেমভ্যালিউপায়ার আর উপলব্ধ নেই (যদি না আপনি এখানে বর্ণিত লিগ্যাসি অ্যাপাচি লাইব্রেরিতে নির্ভরতা যুক্ত করেন )।
টেড হপ

108

যদি আপনি স্প্রিং ফ্রেমওয়ার্ক ব্যবহার করেন:

public static void main(String[] args) {
    String uri = "http://my.test.com/test?param1=ab&param2=cd&param2=ef";
    MultiValueMap<String, String> parameters =
            UriComponentsBuilder.fromUriString(uri).build().getQueryParams();
    List<String> param1 = parameters.get("param1");
    List<String> param2 = parameters.get("param2");
    System.out.println("param1: " + param1.get(0));
    System.out.println("param2: " + param2.get(0) + "," + param2.get(1));
}

তুমি পাবে:

param1: ab
param2: cd,ef

1
ইউআরএল ব্যবহারের জন্যUriComponentsBuilder.fromHttpUrl(url)
লু 55

51

গুগল পেয়ারা ব্যবহার করুন এবং এটি 2 লাইনে করুন:

import java.util.Map;
import com.google.common.base.Splitter;

public class Parser {
    public static void main(String... args) {
        String uri = "https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback";
        String query = uri.split("\\?")[1];
        final Map<String, String> map = Splitter.on('&').trimResults().withKeyValueSeparator('=').split(query);
        System.out.println(map);
    }
}

যা আপনাকে দেয়

{client_id=SS, response_type=code, scope=N_FULL, access_type=offline, redirect_uri=http://localhost/Callback}

18
নির্বাচিত উত্তরে বর্ণিত ইউআরএল ডিকোডিং সম্পর্কে কী?
ক্লিন্ট ইস্টউড

7
এটি একই নামের একাধিক কীতে সন্দেহও করে। জাভাডোকদের মতে এটি একটি অবৈধআর্গুমেন্টএক্সেপশন নিক্ষেপ করবে
jontro

5
ম্যানুয়ালি বিভক্ত হওয়ার পরিবর্তে uriআপনার ব্যবহার new java.net.URL(uri).getQuery()করা উচিত কারণ এটি আপনাকে URL এ ফ্রি ইনপুট বৈধতা কিনে।
avgvstvs

1
ডিকোডিংয়ের জন্য: চূড়ান্ত মানচিত্র <স্ট্রিং, স্ট্রিং> ক্যোয়ারি ওয়ার্স = ম্যাপস ট্রান্সফর্মভ্যালু (মানচিত্র, নতুন ফাংশন <স্ট্রিং, স্ট্রিং> () map @ ওভাররাইড পাবলিক স্ট্রিং প্রয়োগ করুন (স্ট্রিং মান) {URL {ডেকোডার.ডেকোড (মান, "ইউটিএফ- 8 ");} ক্যাচ (অসমর্থিত এনকোডিংএক্সেপশন ই) {// টোডো স্বয়ংক্রিয়ভাবে উত্পাদিত ক্যাচ ব্লক ই.প্রিন্টস্ট্যাকট্রেস ();} ফেরতের মান;}});
ফ্রেইকেহেড

11
সতর্কতামূলক !! এটি করা নিরাপদ নয় যেহেতু ক্যোরি স্ট্রিংয়ে সদৃশ কী থাকলে সেখানে splitter.split()ফেলে দেওয়া হবে IllegalArgumentExceptionস্ট্যাকওভারফ্লো
অ্যান্ডারসন ২

31

আমি সবচেয়ে সংক্ষিপ্ততম পথটি পেয়েছি এটি হ'ল:

MultiValueMap<String, String> queryParams =
            UriComponentsBuilder.fromUriString(url).build().getQueryParams();

আপডেট: UriComponentsBuilder স্প্রিং থেকে আসে। এখানে লিঙ্ক


3
এই ইউরিকম্পোন্টস বিল্ডার শ্রেণি কোথা থেকে এসেছে তা না জেনে এটি খুব কার্যকর নয়।
টমাস

3
এটি লক্ষণীয় যে আপনি যদি ইতিমধ্যে স্প্রিং ব্যবহার করছেন তবে এটি কেবলমাত্র ভাল ধারণা। আপনি যদি বসন্ত ব্যবহার না করেন তবে আপনি এড়াতে চাইবেন। samatkinson.com/why-i-hate-spring
নিক

1
এনবি এটিতে ইউআরআই লাগে। জাভার ইউআরআই-এর সংস্করণ ইউআরএলগুলির সুপারসেট নয় (এ কারণেই টুরিটি ব্যতিক্রম ছুঁড়ে ফেলতে পারে)।
অ্যাডাম জেন্ট

18

অ্যান্ড্রয়েডের জন্য, যদি আপনি আপনার প্রকল্পে OkHttp ব্যবহার করছেন। আপনি এই এক নজরে পেতে পারেন। এটি সহজ এবং সহায়ক।

final HttpUrl url = HttpUrl.parse(query);
if (url != null) {
    final String target = url.queryParameter("target");
    final String id = url.queryParameter("id");
}

এইচটিপিআরল হ'ল এক অদ্ভুত নাম তবে এটি ঠিক আমার প্রয়োজন। ধন্যবাদ।
গুইসিম

10

জাভা 8 একটি বিবৃতি

বিশ্লেষণের জন্য ইউআরএল দেওয়া হয়েছে:

URL url = new URL("https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback");

এই সমাধানটি জোড়ার একটি তালিকা সংগ্রহ করে:

List<AbstractMap.SimpleEntry<String, String>> list = 
        Pattern.compile("&").splitAsStream(url.getQuery())
        .map(s -> Arrays.copyOf(s.split("="), 2))
        .map(o -> new AbstractMap.SimpleEntry<String, String>(decode(o[0]), decode(o[1])))
        .collect(toList());

অন্যদিকে এই সমাধানটি একটি মানচিত্র সংগ্রহ করে (একটি url এ একই নামের সাথে আলাদা আলাদা মান থাকতে পারে তবে বিভিন্ন মান থাকতে পারে) values

Map<String, List<String>> list = 
        Pattern.compile("&").splitAsStream(url.getQuery())
        .map(s -> Arrays.copyOf(s.split("="), 2))
        .collect(groupingBy(s -> decode(s[0]), mapping(s -> decode(s[1]), toList())));

উভয় সমাধানের প্যারামিটারগুলি সঠিকভাবে ডিকোড করতে একটি ইউটিলিটি ফাংশন ব্যবহার করতে হবে।

private static String decode(final String encoded) {
    try {
        return encoded == null ? null : URLDecoder.decode(encoded, "UTF-8");
    } catch(final UnsupportedEncodingException e) {
        throw new RuntimeException("Impossible: UTF-8 is a required encoding", e);
    }
}

4
এটি জাভা 8 অনেলাইনারের চেয়ে জাভা 8 পদ্ধতির বেশি।
স্টিফান

@ স্টেফান ভাল :) সম্ভবত উভয়ই। তবে আপনি যদি এই সমাধানটি পছন্দ করেন তবে আমি বুঝতে আগ্রহী।
ফ্রিদেব

3
আইএমও, অনলাইনারটি সংক্ষিপ্ত হওয়া উচিত এবং একাধিক লাইনে থাকা উচিত নয়।
স্টিফান

1
এখানে একাধিক বিবৃতি জড়িত রয়েছে।
স্টিফান

2
আমি অনুমান করি আপনি একটি একক লাইনে একটি সম্পূর্ণ ক্লাস লিখতে পারেন, তবে এটি সাধারণত "ওয়ান-লাইনার" শব্দটি দ্বারা বোঝানো হয় না।
অভিজিৎ সরকার

10

আপনি যদি সার্লেটলেট ব্যবহার করছেন তবে এটি ব্যবহার করে দেখুন G

request.getParameterMap()

এই অনুরোধের পরামিতিগুলির একটি java.util.Map প্রদান করে।

রিটার্নস: মানচিত্রের মান হিসাবে কী এবং প্যারামিটার মান হিসাবে পরামিতি নাম যুক্ত একটি অপরিবর্তনীয় java.util.Map। প্যারামিটার মানচিত্রে কীগুলি স্ট্রিং প্রকারের। প্যারামিটার মানচিত্রে মানগুলি স্ট্রিং অ্যারে প্রকারের।

( জাভা ডক )


এটি স্প্রিং ওয়েবের সাথে আপনার কন্ট্রোলারে যেমন টাইপের একটি প্যারামিটার রাখতে পারে HttpServletRequestতা নিয়ে কাজ করে এবং এটি MockHttpServletRequestমক এমভিসি ইউনিট পরীক্ষায়ও কাজ করে।
গেমসলুটস

8

আপনি যদি জাভা 8 ব্যবহার করছেন এবং আপনি কয়েকটি পুনরায় ব্যবহারযোগ্য পদ্ধতি লিখতে ইচ্ছুক হন তবে আপনি এটি এক লাইনে করতে পারেন।

private Map<String, List<String>> parse(final String query) {
    return Arrays.asList(query.split("&")).stream().map(p -> p.split("=")).collect(Collectors.toMap(s -> decode(index(s, 0)), s -> Arrays.asList(decode(index(s, 1))), this::mergeLists));
}

private <T> List<T> mergeLists(final List<T> l1, final List<T> l2) {
    List<T> list = new ArrayList<>();
    list.addAll(l1);
    list.addAll(l2);
    return list;
}

private static <T> T index(final T[] array, final int index) {
    return index >= array.length ? null : array[index];
}

private static String decode(final String encoded) {
    try {
        return encoded == null ? null : URLDecoder.decode(encoded, "UTF-8");
    } catch(final UnsupportedEncodingException e) {
        throw new RuntimeException("Impossible: UTF-8 is a required encoding", e);
    }
}

তবে এটি একটি নিষ্ঠুর লাইন।


3

অ্যান্ড্রয়েডে, প্যাকেজ android.net এ একটি উরি ক্লাস রয়েছে । লক্ষ্য করুন উরি অংশ android.net , যখন কোনো URI অংশ java.net

উরি ক্লাসে একটি ক্যোয়ারী থেকে মূল-মান জোড়া বের করার জন্য অনেকগুলি ক্রিয়াকলাপ রয়েছে। এখানে চিত্র বর্ণনা লিখুন

নিম্নলিখিত ফাংশনটি হ্যাশম্যাপ আকারে মূল-মান জোড়া দেয়।

জাভাতে:

Map<String, String> getQueryKeyValueMap(Uri uri){
    HashMap<String, String> keyValueMap = new HashMap();
    String key;
    String value;

    Set<String> keyNamesList = uri.getQueryParameterNames();
    Iterator iterator = keyNamesList.iterator();

    while (iterator.hasNext()){
        key = (String) iterator.next();
        value = uri.getQueryParameter(key);
        keyValueMap.put(key, value);
    }
    return keyValueMap;
}

কোটলিনে:

fun getQueryKeyValueMap(uri: Uri): HashMap<String, String> {
        val keyValueMap = HashMap<String, String>()
        var key: String
        var value: String

        val keyNamesList = uri.queryParameterNames
        val iterator = keyNamesList.iterator()

        while (iterator.hasNext()) {
            key = iterator.next() as String
            value = uri.getQueryParameter(key) as String
            keyValueMap.put(key, value)
        }
        return keyValueMap
    }

2

উল্লিখিত মন্তব্য এবং সমাধানগুলি ব্যবহার করে, আমি মানচিত্র <স্ট্রিং, অবজেক্ট> ব্যবহার করে সমস্ত ক্যোয়ারী প্যারামিটারগুলি সংরক্ষণ করছি যেখানে অবজেক্টগুলি স্ট্রিং বা সেট <স্ট্রিং> হতে পারে। সমাধানটি নীচে দেওয়া হল। প্রথমে ইউআরএলটিকে বৈধতা দেওয়ার জন্য কিছু ধরণের url ভ্যালিডেটর ব্যবহার করার পরামর্শ দেওয়া হয় এবং তারপরে রূপান্তরকুরিস্ট্রিংটোম্যাপ পদ্ধতিতে কল করুন।

private static final String DEFAULT_ENCODING_SCHEME = "UTF-8";

public static Map<String, Object> convertQueryStringToMap(String url) throws UnsupportedEncodingException, URISyntaxException {
    List<NameValuePair> params = URLEncodedUtils.parse(new URI(url), DEFAULT_ENCODING_SCHEME);
    Map<String, Object> queryStringMap = new HashMap<>();
    for(NameValuePair param : params){
        queryStringMap.put(param.getName(), handleMultiValuedQueryParam(queryStringMap, param.getName(), param.getValue()));
    }
    return queryStringMap;
}

private static Object handleMultiValuedQueryParam(Map responseMap, String key, String value) {
    if (!responseMap.containsKey(key)) {
        return value.contains(",") ? new HashSet<String>(Arrays.asList(value.split(","))) : value;
    } else {
        Set<String> queryValueSet = responseMap.get(key) instanceof Set ? (Set<String>) responseMap.get(key) : new HashSet<String>();
        if (value.contains(",")) {
            queryValueSet.addAll(Arrays.asList(value.split(",")));
        } else {
            queryValueSet.add(value);
        }
        return queryValueSet;
    }
}

2

কোটলিন সংস্করণে আমি যেতে পেরেছিলাম এটি কীভাবে গুগলের শীর্ষ ফলাফল।

@Throws(UnsupportedEncodingException::class)
fun splitQuery(url: URL): Map<String, List<String>> {

    val queryPairs = LinkedHashMap<String, ArrayList<String>>()

    url.query.split("&".toRegex())
            .dropLastWhile { it.isEmpty() }
            .map { it.split('=') }
            .map { it.getOrEmpty(0).decodeToUTF8() to it.getOrEmpty(1).decodeToUTF8() }
            .forEach { (key, value) ->

                if (!queryPairs.containsKey(key)) {
                    queryPairs[key] = arrayListOf(value)
                } else {

                    if(!queryPairs[key]!!.contains(value)) {
                        queryPairs[key]!!.add(value)
                    }
                }
            }

    return queryPairs
}

এবং এক্সটেনশন পদ্ধতি

fun List<String>.getOrEmpty(index: Int) : String {
    return getOrElse(index) {""}
}

fun String.decodeToUTF8(): String { 
    URLDecoder.decode(this, "UTF-8")
}

1
সমান .ণ stackoverflow.com/users/1203812/matthe-herod 50/50 প্রচেষ্টা কিন্তু সহ-লেখক করতে পারবেন না।
গ্রাহাম স্মিথ

2

ইউআরআই কোয়েরি অংশের ডিকোডিংয়ের জন্য ব্যবহারের জন্য প্রস্তুত সমাধান (সহ ডিকোডিং এবং মাল্টি প্যারামিটার মানগুলি)

মন্তব্য

আমি @ Pr0gr4mm3r দ্বারা উপলব্ধ কোড সহ সুখী ছিল না https://stackoverflow.com/a/13592567/1211082 । স্ট্রিম-ভিত্তিক সমাধানটি ইউআরএলডিকোডিং করে না, পরিবর্তনীয় সংস্করণ ক্লাম্পসি।

এইভাবে আমি একটি সমাধান ব্যাখ্যা করেছি

  • একটি ইউআরআই ক্যোয়ারী অংশকে a তে বিভক্ত করতে পারে Map<String, List<Optional<String>>>
  • একাধিক মান পরিচালনা করতে পারেএকই প্যারামিটার নামের জন্য
  • মান ব্যতীত সঠিকভাবে ( Optional.empty()পরিবর্তে) পরামিতিগুলি উপস্থাপন করতে পারেnull )
  • প্যারামিটারের নাম এবং মানগুলি ডিকোড করে মাধ্যমেURLdecode
  • জাভা 8 স্ট্রিমের উপর ভিত্তি করে
  • সরাসরি ব্যবহারযোগ্য (নীচে আমদানি সহ কোড দেখুন)
  • একটি চেক করা ব্যতিক্রম বাঁক মাধ্যমে এখানে যথাযথ ত্রুটি পরিচালনা জন্য অনুমতি দেয় ( UnsupportedEncodingExceptionএকটি রানটাইম ব্যতিক্রম মধ্যে RuntimeUnsupportedEncodingException(ফাংশন চেক করা ব্যতিক্রম নিক্ষেপ মধ্যে নিয়মিত ফাংশন মোড়ানো যে স্ট্রিম নিয়ে পারস্পরিক পারেন। ব্যাথা হয়। আর Scala Tryজাভা ভাষা ডিফল্ট উপলব্ধ নয়।)

জাভা কোড

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;
import static java.util.stream.Collectors.*;

public class URIParameterDecode {
    /**
     * Decode parameters in query part of a URI into a map from parameter name to its parameter values.
     * For parameters that occur multiple times each value is collected.
     * Proper decoding of the parameters is performed.
     * 
     * Example
     *   <pre>a=1&b=2&c=&a=4</pre>
     * is converted into
     *   <pre>{a=[Optional[1], Optional[4]], b=[Optional[2]], c=[Optional.empty]}</pre>
     * @param query the query part of an URI 
     * @return map of parameters names into a list of their values.
     *         
     */
    public static Map<String, List<Optional<String>>> splitQuery(String query) {
        if (query == null || query.isEmpty()) {
            return Collections.emptyMap();
        }

        return Arrays.stream(query.split("&"))
                    .map(p -> splitQueryParameter(p))
                    .collect(groupingBy(e -> e.get0(), // group by parameter name
                            mapping(e -> e.get1(), toList())));// keep parameter values and assemble into list
    }

    public static Pair<String, Optional<String>> splitQueryParameter(String parameter) {
        final String enc = "UTF-8";
        List<String> keyValue = Arrays.stream(parameter.split("="))
                .map(e -> {
                    try {
                        return URLDecoder.decode(e, enc);
                    } catch (UnsupportedEncodingException ex) {
                        throw new RuntimeUnsupportedEncodingException(ex);
                    }
                }).collect(toList());

        if (keyValue.size() == 2) {
            return new Pair(keyValue.get(0), Optional.of(keyValue.get(1)));
        } else {
            return new Pair(keyValue.get(0), Optional.empty());
        }
    }

    /** Runtime exception (instead of checked exception) to denote unsupported enconding */
    public static class RuntimeUnsupportedEncodingException extends RuntimeException {
        public RuntimeUnsupportedEncodingException(Throwable cause) {
            super(cause);
        }
    }

    /**
     * A simple pair of two elements
     * @param <U> first element
     * @param <V> second element
     */
    public static class Pair<U, V> {
        U a;
        V b;

        public Pair(U u, V v) {
            this.a = u;
            this.b = v;
        }

        public U get0() {
            return a;
        }

        public V get1() {
            return b;
        }
    }
}

স্কাল কোড

... এবং সম্পূর্ণতার জন্য আমি স্ক্যালায় সলিউশন এবং সৌন্দর্যের দ্বারা আধিপত্যের সমাধান দিতে প্রতিরোধ করতে পারি না

import java.net.URLDecoder

object Decode {
  def main(args: Array[String]): Unit = {
    val input = "a=1&b=2&c=&a=4";
    println(separate(input))
  }

  def separate(input: String) : Map[String, List[Option[String]]] = {
    case class Parameter(key: String, value: Option[String])

    def separateParameter(parameter: String) : Parameter =
      parameter.split("=")
               .map(e => URLDecoder.decode(e, "UTF-8")) match {
      case Array(key, value) =>  Parameter(key, Some(value))
      case Array(key) => Parameter(key, None)
    }

    input.split("&").toList
      .map(p => separateParameter(p))
      .groupBy(p => p.key)
      .mapValues(vs => vs.map(p => p.value))
  }
}

1

জাভা 8 সংস্করণে কেবল একটি আপডেট

public Map<String, List<String>> splitQuery(URL url) {
    if (Strings.isNullOrEmpty(url.getQuery())) {
        return Collections.emptyMap();
    }
    return Arrays.stream(url.getQuery().split("&"))
            .map(this::splitQueryParameter)
            .collect(Collectors.groupingBy(SimpleImmutableEntry::getKey, LinkedHashMap::new, **Collectors**.mapping(Map.Entry::getValue, **Collectors**.toList())));
}

সংগ্রাহকদের সাথে ম্যাপিং এবং টোলিস্ট () পদ্ধতিগুলি ব্যবহার করতে হবে যা শীর্ষ উত্তরে উল্লেখ করা হয়নি। অন্যথায় এটি আইডিইতে সংকলন ত্রুটি নিক্ষেপ করবে


দেখে মনে হচ্ছে আপনার নিজের splitQueryParameters()পদ্ধতিটিও ভাগ করে নেওয়া দরকার ? এবং এর সাথে কি **Collectors**?
কারবি

1

Https://stackoverflow.com/a/51024552/3286489 থেকে প্রাথমিক রেফারেন্স সহ কোটলিনের উত্তর , তবে কোডগুলি সাফ করে উন্নত সংস্করণ সহ এর 2 টি সংস্করণ সরবরাহ করা হয়েছে এবং অপরিবর্তনীয় সংগ্রহের ক্রিয়াকলাপ ব্যবহার করুন

java.net.URIক্যোয়ারি নিষ্কাশন করতে ব্যবহার করুন । তারপরে নীচে প্রদত্ত এক্সটেনশন ফাংশনগুলি ব্যবহার করুন

  1. ধরে নিচ্ছি আপনি কেবলমাত্র ক্যোয়ারির শেষ মানটি page2&page3পেতে চান অর্থাৎ পাবেন {page=3}, নীচের এক্সটেনশন ফাংশনটি ব্যবহার করুন
    fun URI.getQueryMap(): Map<String, String> {
        if (query == null) return emptyMap()

        return query.split("&")
                .mapNotNull { element -> element.split("=")
                        .takeIf { it.size == 2 && it.none { it.isBlank() } } }
                .associateBy({ it[0].decodeUTF8() }, { it[1].decodeUTF8() })
    }

    private fun String.decodeUTF8() = URLDecoder.decode(this, "UTF-8") // decode page=%22ABC%22 to page="ABC"
  1. ধরে নিচ্ছি যে আপনি কোয়েরির জন্য সমস্ত মানের একটি তালিকা চান, তাই page2&page3পাবেন{page=[2, 3]}
    fun URI.getQueryMapList(): Map<String, List<String>> {
        if (query == null) return emptyMap()

        return query.split("&")
                .distinct()
                .mapNotNull { element -> element.split("=")
                        .takeIf { it.size == 2 && it.none { it.isBlank() } } }
                .groupBy({ it[0].decodeUTF8() }, { it[1].decodeUTF8() })
    }

    private fun String.decodeUTF8() = URLDecoder.decode(this, "UTF-8") // decode page=%22ABC%22 to page="ABC"

নীচে হিসাবে এটি ব্যবহার করার উপায়

    val uri = URI("schema://host/path/?page=&page=2&page=2&page=3")
    println(uri.getQueryMapList()) // Result is {page=[2, 3]}
    println(uri.getQueryMap()) // Result is {page=3}

1

নেট নামক একটি দুর্দান্ত ক্যোরিয় স্ট্রিং পার্সার সরবরাহ করে QueryStringDecoder। কোডের একটি লাইনে, এটি প্রশ্নের URL টি পার্স করতে পারে। আমি পছন্দ করি কারণ এটি ধরা বা নিক্ষেপ করার প্রয়োজন হয় না java.net.MalformedURLException

এক লাইনে:

Map<String, List<String>> parameters = new QueryStringDecoder(url).parameters();

জাভাডোকগুলি এখানে দেখুন: https://netty.io/4.1/api/io/netty/handler/codec/http/QueryStringDecoder.html

এখানে একটি সংক্ষিপ্ত, স্ব অন্তর্ভুক্ত, সঠিক উদাহরণ:

import io.netty.handler.codec.http.QueryStringDecoder;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Map;

public class UrlParse {

  public static void main(String... args) {
    String url = "https://google.com.ua/oauth/authorize?client_id=SS&response_type=code&scope=N_FULL&access_type=offline&redirect_uri=http://localhost/Callback";
    QueryStringDecoder decoder = new QueryStringDecoder(url);
    Map<String, List<String>> parameters = decoder.parameters();
    print(parameters);
  }

  private static void print(final Map<String, List<String>> parameters) {
    System.out.println("NAME               VALUE");
    System.out.println("------------------------");
    parameters.forEach((key, values) ->
        values.forEach(val ->
            System.out.println(StringUtils.rightPad(key, 19) + val)));
  }
}

যা উত্পন্ন করে

NAME               VALUE
------------------------
client_id          SS
response_type      code
scope              N_FULL
access_type        offline
redirect_uri       http://localhost/Callback

0

এখানে উত্তর দেওয়া কারণ এটি একটি জনপ্রিয় থ্রেড। এটি কোটলিনের একটি পরিষ্কার সমাধান যা প্রস্তাবিত UrlQuerySanitizerএপিআই ব্যবহার করে । সরকারী ডকুমেন্টেশন দেখুন । আমি প্যারামগুলি একত্রিত করতে এবং প্রদর্শন করতে একটি স্ট্রিং বিল্ডার যুক্ত করেছি।

    var myURL: String? = null

    if (intent.hasExtra("my_value")) {
        myURL = intent.extras.getString("my_value")
    } else {
        myURL = intent.dataString
    }

    val sanitizer = UrlQuerySanitizer(myURL)
    // We don't want to manually define every expected query *key*, so we set this to true
    sanitizer.allowUnregisteredParamaters = true
    val parameterNamesToValues: List<UrlQuerySanitizer.ParameterValuePair> = sanitizer.parameterList
    val parameterIterator: Iterator<UrlQuerySanitizer.ParameterValuePair> = parameterNamesToValues.iterator()

    // Helper simply so we can display all values on screen
    val stringBuilder = StringBuilder()

    while (parameterIterator.hasNext()) {
        val parameterValuePair: UrlQuerySanitizer.ParameterValuePair = parameterIterator.next()
        val parameterName: String = parameterValuePair.mParameter
        val parameterValue: String = parameterValuePair.mValue

        // Append string to display all key value pairs
        stringBuilder.append("Key: $parameterName\nValue: $parameterValue\n\n")
    }

    // Set a textView's text to display the string
    val paramListString = stringBuilder.toString()
    val textView: TextView = findViewById(R.id.activity_title) as TextView
    textView.text = "Paramlist is \n\n$paramListString"

    // to check if the url has specific keys
    if (sanitizer.hasParameter("type")) {
        val type = sanitizer.getValue("type")
        println("sanitizer has type param $type")
    }

0

হ্রাস এবং ptionচ্ছিক সহ আমার সমাধান এখানে :

private Optional<SimpleImmutableEntry<String, String>> splitKeyValue(String text) {
    String[] v = text.split("=");
    if (v.length == 1 || v.length == 2) {
        String key = URLDecoder.decode(v[0], StandardCharsets.UTF_8);
        String value = v.length == 2 ? URLDecoder.decode(v[1], StandardCharsets.UTF_8) : null;
        return Optional.of(new SimpleImmutableEntry<String, String>(key, value));
    } else
        return Optional.empty();
}

private HashMap<String, String> parseQuery(URI uri) {
    HashMap<String, String> params = Arrays.stream(uri.getQuery()
            .split("&"))
            .map(this::splitKeyValue)
            .filter(Optional::isPresent)
            .map(Optional::get)
            .reduce(
                // initial value
                new HashMap<String, String>(), 
                // accumulator
                (map, kv) -> {
                     map.put(kv.getKey(), kv.getValue()); 
                     return map;
                }, 
                // combiner
                (a, b) -> {
                     a.putAll(b); 
                     return a;
                });
    return params;
}
  • আমি সদৃশ প্যারামিটারগুলি অগ্রাহ্য করি (আমি সর্বশেষটি গ্রহণ করি)।
  • আমি Optional<SimpleImmutableEntry<String, String>>পরে আবর্জনা উপেক্ষা করার জন্য ব্যবহার করি
  • হ্রাসটি খালি মানচিত্রের সাথে শুরু হয়, তারপরে এটি প্রতিটি সিম্পিমিটেবল এন্ট্রিতে স্থাপন করুন

আপনি যদি জিজ্ঞাসা করেন, হ্রাস করার জন্য সর্বশেষ প্যারামিটারে এই অদ্ভুত সংযোগকারী প্রয়োজন যা কেবলমাত্র সমান্তরাল স্ট্রিমগুলিতে ব্যবহৃত হয়। এর লক্ষ্যটি দুটি মধ্যবর্তী ফলাফলকে মার্জ করা (এখানে হ্যাশম্যাপ)।


-1

আপনি যদি স্প্রিং ব্যবহার করছেন, @RequestParam Map<String,String> আপনার নিয়ামক পদ্ধতিতে টাইপের একটি যুক্তি যুক্ত করুন , এবং স্প্রিং আপনার জন্য মানচিত্রটি তৈরি করবে!

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.