2011-06-07 10 views
17

तो मैं इस तरह स्काला में एक नक्शा है:स्कैला में JSON पर एक मानचित्र को क्रमबद्ध कैसे करें?

val m = Map[String, String](
    "a" -> "theA", 
    "b" -> "theB", 
    "c" -> "theC", 
    "d" -> "theD", 
    "e" -> "theE" 
) 

और मैं लिफ्ट json का उपयोग कर JSON स्ट्रिंग में इस संरचना को क्रमानुसार करना चाहते हैं।

क्या आप में से कोई भी यह कैसे जानता है?

+0

यह पोस्ट शायद उपयोगी है http://albertech.blogspot.com/2017/02/convert-nested-map-and-list-data।एचटीएमएल – jar

उत्तर

24

इस बारे में कैसे?

implicit val formats = net.liftweb.json.DefaultFormats 
import net.liftweb.json.JsonAST._ 
import net.liftweb.json.Extraction._ 
import net.liftweb.json.Printer._ 
val m = Map[String, String](
    "a" -> "theA", 
    "b" -> "theB", 
    "c" -> "theC", 
    "d" -> "theD", 
    "e" -> "theE" 
) 
println(compact(render(decompose(m)))) 

उत्पादन:

{"e":"theE","a":"theA","b":"theB","c":"theC","d":"theD"} 

संपादित करें: यदि आप नवीनतम स्काला 2.10 उपयोग कर रहे हैं .toMap

+5

जब मैं टाइप को scala.collections.mutable.Map में बदलता हूं, तो आउटपुट बन जाता है: [{"_1": "d", "_ 2": "thed"}, {"_ 1": "a", "_ 2 ":" थिया "}, {" _ 1 ":" सी "," _ 2 ":" theC "}, {" _ 1 ":" ख "," _ 2 ":" theB "}, {" _ 1 ":" ई "," _ 2 ":" theE "}], जो मुझे दुखी करता है। –

+4

इसके लिए एक आसान कामकाज है - बस एक अपरिवर्तनीय मानचित्र प्राप्त करने के लिए म्यूटेबल मानचित्र पर टोटो करें, और फिर चीजें ठीक से काम करती हैं। –

+1

लेकिन यदि आप मानचित्र में तत्वों के क्रम को संरक्षित करना चाहते हैं तो क्या होगा? असल में, कैसे एक LinkedHashMap json-serialize करने के लिए? कॉलिंग टूमैप प्रविष्टियों के क्रम को संशोधित कर सकता है। – teo

22

:

एक scala.collections.mutable.Map के लिए, आप यह पहली अपरिवर्तनीय मानचित्र में बदलने चाहिए। एक्स और ऊपर:

println(scala.util.parsing.json.JSONObject(m)) 
+1

इसे स्कैला 2.11 और उसके बाद से हटा दिया गया है। – Soid

+1

@ ध्वनि ऐसा लगता है कि यह अभी भी वहां है: http://www.scala-lang.org/api/2.11.8/scala-parser-combinators/#scala.util.parsing.json.JSONObject – nevets1219

+0

मैं कहीं गलती कर सकता हूं । लेकिन क्या आप इसका इस्तेमाल करने में सक्षम थे? स्कैला-पार्सर-संयोजकों का आप किस संस्करण का उपयोग करते थे (एक पूर्ण मेवेन निर्भरता सहायक होगी)? – Soid

0

इयनार के समाधान के समान, आप ऐसा करने के लिए JSONObject Parser Combinators से उपयोग कर सकते हैं। ध्यान दें कि यह रिकर्स नहीं करता है, आपको इसे स्वयं करने की आवश्यकता होगी। पुस्तकालय में डेटा संरचनाओं की सूची के लिए JSONArray भी शामिल है। निम्नलिखित की तरह कुछ नेस्टेड संरचनाओं के बारे में नोएल की चिंताओं को संबोधित करेंगे। यह उदाहरण मनमाने ढंग से स्तर की पुनरावृत्ति नहीं करता है, लेकिन सूची [मानचित्र [स्ट्रिंग, कोई भी]] के मान को संभालेगा।

import scala.util.parsing.json.{JSONArray, JSONObject} 

def toJson(m : Map[String, Any]): String = JSONObject(
    m.mapValues { 
    case mp: Map[String, Any] => JSONObject(mp) 
    case lm: List[Map[String, Any]] => JSONArray(lm.map(JSONObject(_))) 
    case x => x 
    } 
).toString 
4

आप अपना खुद का सुंदर आसानी से (याय, कोई निर्भरता नहीं) रोल कर सकते हैं। यह एक प्रकार की बुनियादी हैंडलिंग करता है और JSONObject विपरीत प्रत्यावर्तन कि उल्लेख किया गया था क्या करेंगे:

import scala.collection.mutable.ListBuffer 

object JsonConverter { 
    def toJson(o: Any) : String = { 
    var json = new ListBuffer[String]() 
    o match { 
     case m: Map[_,_] => { 
     for ((k,v) <- m) { 
      var key = escape(k.asInstanceOf[String]) 
      v match { 
      case a: Map[_,_] => json += "\"" + key + "\":" + toJson(a) 
      case a: List[_] => json += "\"" + key + "\":" + toJson(a) 
      case a: Int => json += "\"" + key + "\":" + a 
      case a: Boolean => json += "\"" + key + "\":" + a 
      case a: String => json += "\"" + key + "\":\"" + escape(a) + "\"" 
      case _ => ; 
      } 
     } 
     } 
     case m: List[_] => { 
     var list = new ListBuffer[String]() 
     for (el <- m) { 
      el match { 
      case a: Map[_,_] => list += toJson(a) 
      case a: List[_] => list += toJson(a) 
      case a: Int => list += a.toString() 
      case a: Boolean => list += a.toString() 
      case a: String => list += "\"" + escape(a) + "\"" 
      case _ => ; 
      } 
     } 
     return "[" + list.mkString(",") + "]" 
     } 
     case _ => ; 
    } 
    return "{" + json.mkString(",") + "}" 
    } 

    private def escape(s: String) : String = { 
    return s.replaceAll("\"" , "\\\\\""); 
    } 
} 

आप

println(JsonConverter.toJson(
    Map("a"-> 1, 
     "b" -> Map(
      "nes\"ted" -> "yeah{\"some\":true"), 
      "c" -> List(
       1, 
       2, 
       "3", 
       List(
        true, 
        false, 
        true, 
        Map(
         "1"->"two", 
         "3"->"four" 
        ) 
       ) 
      ) 
     ) 
    ) 
) 

{"a":1,"b":{"nes\"ted":"yeah{\"some\":true"},"c":[1,2,"3",[true,false,true,{"1":"two","3":"four"}]]} 

(यह एक Coinbase GDAX पुस्तकालय मैं लिखा है के भाग की तरह कार्रवाई में इसे देख सकते हैं , util.scala देखें)

2

यदि आप खेलने के ढांचे का उपयोग कर रहे इस आसान तरीका का उपयोग कर सकते हैं:

import play.api.libs.json._ 

Json.toJson(<your_map>) 
1

यह कोड कई अलग-अलग वस्तुओं को परिवर्तित करेगा, और scala.util.parsing.json._ के अंतर्निहित किसी भी पुस्तकालय की आवश्यकता नहीं है। यह किनारों के रूप में पूर्णांक वाले मानचित्र जैसे किनारे के मामलों को सही तरीके से संभाल नहीं पाएगा।

import scala.util.parsing.json.{JSONArray, JSONObject} 
def toJson(arr: List[Any]): JSONArray = { 
    JSONArray(arr.map { 
    case (innerMap: Map[String, Any]) => toJson(innerMap) 
    case (innerArray: List[Any])  => toJson(innerArray) 
    case (other)      => other 
    }) 
} 
def toJson(map: Map[String, Any]): JSONObject = { 
    JSONObject(map.map { 
    case (key, innerMap: Map[String, Any]) => 
     (key, toJson(innerMap)) 
    case (key, innerArray: List[Any]) => 
     (key, toJson(innerArray)) 
    case (key, other) => 
     (key, other) 
    }) 
} 
0

@ राजा द्वारा उत्तर का पूरक।

उन नेस्टेड वस्तु के लिए, मैं स्थानीय रूप से संशोधित वर्ग मेरी चाहता था इस तरह की तरह toString() के लिए:

case class MList[T]() extends MutableList[T] { override def toString() = "[" + this.toList.mkString(",") + "]" }

तब मानचित्र ऑब्जेक्ट के अंदर, मैं मानक List के बजाय इस MList का उपयोग करें। इस तरह, map ऑब्जेक्ट JSONObject(map).toString() पर कॉल करके ठीक प्रिंट करता है।