JSON

2011-06-28 32 views
7

पर SQLGeography बहुभुज को सुधारें मैं एक वेब सेवा बना रहा हूं जो JSON प्रारूप में भौगोलिक सीमा डेटा प्रदान करता है।JSON

भौगोलिक डेटा किसी तालिका में भूगोल प्रकार का उपयोग कर SQL सर्वर 2008 R2 डेटाबेस में संग्रहीत किया जाता है। मैं पॉलीगॉन डेटा को पाठ के रूप में वापस करने के लिए [ColumnName].ToString() विधि का उपयोग करता हूं।

उदाहरण आउटपुट:

POLYGON ((-6.1646509904325884 56.435153006374627, ... -6.1606079906751 56.4338050060666)) 

MULTIPOLYGON (((-6.1646509904325884 56.435153006374627 0 0, ... -6.1606079906751 56.4338050060666 0 0))) 

ज्योग्राफिक परिभाषाओं या तो अक्षांश/देशांतर जोड़े एक बहुभुज को परिभाषित करने की एक सरणी या कई परिभाषाएं, एक सरणी या बहुभुज (multipolygon) के मामले में के रूप ले सकता है।

मेरे पास निम्न रेगेक्स है जो आउटपुट के आधार पर बहु-आयामी सरणी में मौजूद JSON ऑब्जेक्ट्स में आउटपुट को परिवर्तित करता है।

Regex latlngMatch = new Regex(@"(-?[0-9]{1}\.\d*)\s(\d{2}.\d*)(?:\s0\s0,?)?", RegexOptions.Compiled); 

    private string ConvertPolysToJson(string polysIn) 
    { 
     return this.latlngMatch.Replace(polysIn.Remove(0, polysIn.IndexOf("(")) // remove POLYGON or MULTIPOLYGON 
               .Replace("(", "[") // convert to JSON array syntax 
               .Replace(")", "]"), // same as above 
               "{lng:$1,lat:$2},"); // reformat lat/lng pairs to JSON objects 
    } 

यह वास्तव में बहुत अच्छी तरह से काम कर रहा है और एक ऑपरेशन कॉल के जवाब में मक्खी पर JSON करने के लिए डीबी उत्पादन धर्मान्तरित है।

हालांकि मैं कोई रेगेक्स मास्टर नहीं हूं और String.Replace() पर कॉल भी मेरे लिए अक्षम नहीं हैं।

क्या किसी के पास इसके प्रदर्शन के बारे में कोई सुझाव/टिप्पणियां हैं?

+0

नोट: भौगोलिक परिभाषा केवल जीबी के लिए है, जो रेगेक्स में दिखाई देती है। – James

उत्तर

8

फिर बस इसे बंद करने के लिए मैं समाधान का उपयोग कर अपने स्वयं के प्रश्न का उत्तर दूंगा।

यह विधि एक एमएस एसक्यूएल Geography Type पर ToString() कॉल से आउटपुट लेती है। यदि स्ट्रिंग में लौटाई गई बहुभुज डेटा संरचना जीपीएस अंक शामिल है, तो यह विधि एक JSON स्टिंग पर पार्स और सुधारित होगी।

public static class PolyConverter 
{ 
    static Regex latlngMatch = new Regex(@"(-?\d{1,2}\.\dE-\d+|-?\d{1,2}\.?\d*)\s(-?\d{1,2}\.\dE-\d+|-?\d{1,2}\.?\d*)\s?0?\s?0?,?", RegexOptions.Compiled); 
    static Regex reformat = new Regex(@"\[,", RegexOptions.Compiled); 

    public static string ConvertPolysToJson(string polysIn) 
    { 
     var formatted = reformat.Replace(
         latlngMatch.Replace(
         polysIn.Remove(0, polysIn.IndexOf("(")), ",{lng:$1,lat:$2}") 
         .Replace("(", "[") 
         .Replace(")", "]"), "["); 

     if (polysIn.Contains("MULTIPOLYGON")) 
     { 
      formatted = formatted.Replace("[[", "[") 
           .Replace("]]", "]") 
           .Replace("[[[", "[[") 
           .Replace("]]]", "]]"); 
     } 

     return formatted; 
    } 
} 

यह और भी बेहतर कार्यान्वयन बनाने मेरी apllication के लिए विशिष्ट, लेकिन शायद किसी के लिए उपयोगी हो सकता है और है।

+0

यह एक अच्छा कामकाज है, मेरे लिए ठीक काम करता है –

1

स्ट्रिंग्स .NET में अपरिवर्तनीय हैं, इसलिए जब आप कुछ को बदलते हैं, तो आप पिछली स्ट्रिंग की एक संपादित प्रति बनाते हैं। स्मृति उपयोग के लिए प्रदर्शन के लिए यह इतना महत्वपूर्ण नहीं है।

JSON.net

या StringBuilder का उपयोग यह ठीक से उत्पन्न करने के लिए देखें।

StringBuilder sb = new StringBuilder(); 
sb.AppendFormat(); 
+0

मुझे यह पता है, और मैं पहले से ही JSON.Net का उपयोग करता हूं। चूंकि तारों में कोई डिलीमीटर नहीं होता है, इसलिए मैं उन्हें थूक नहीं सकता और फिर उन्हें स्ट्रिंगबिल्डर या JSON ऑब्जेक्ट में जोड़ सकता हूं। मैं लेट/लांग जोड़े का पता लगा सकता हूं लेकिन स्टिंग में ब्रैकेटिंग भी महत्वपूर्ण है क्योंकि यह सरणी की गहराई को दर्शाती है, अन्यथा मैं सिर्फ अपने मैचों को ले सकता हूं और जेएसओएन ऑब्जेक्ट बना सकता हूं और ब्रैकेट की परवाह नहीं करता। अनिवार्य रूप से ये स्ट्रिंग लगभग JSON ऑब्जेक्ट्स हैं, फिर भी उन्हें JSON वाक्यविन्यास में सुधार करने की आवश्यकता है। – James

4

, दक्षता के बारे में अपने प्रश्न का उत्तर देने इस विशेष मामले के लिए, मुझे नहीं लगता कि बदलें कि बनाम रेगुलर एक्सप्रेशन से है कि एक अंतर का बड़ा होने जा रहा है है। हम वास्तव में कुछ बदल रहे हैं कुछ कोष्ठक और अल्पविराम है। निजी तौर पर, मैं वेब अनुप्रयोगों के लिए टीएसक्यूएल में चीजें करना पसंद करता हूं क्योंकि मैं वेब सर्वर की बजाय SQL सर्वर पर कम्प्यूटेशनल काम को ऑफ़लोड कर सकता हूं। मेरे मामले में मेरे पास बहुत सारे डेटा हैं जो मैं मानचित्र के लिए उत्पन्न कर रहा हूं और इसलिए वेब सर्वर को डेटा के कई रूपांतरणों के साथ छेड़छाड़ नहीं करना चाहता हूं। इसके अतिरिक्त, प्रदर्शन के लिए, मैं आमतौर पर SQL सर्वर पर अधिक अश्वशक्ति डालता हूं, क्योंकि मैं एक वेबसर्वर करता हूं, इसलिए यदि दो कार्यों के बीच कुछ अंतर है, तो बदलें कम कुशलता से कम से कम एक सर्वर द्वारा संभाला जा रहा है और अधिक संसाधनों। आम तौर पर, मैं चाहता हूं कि मेरे वेबसर्वर ग्राहकों को कनेक्शन और मेरे SQL सर्वर डेटा कंप्यूटेशंस को संभालने के लिए कनेक्शन चाहते हैं। यह मेरी वेब सर्वर स्क्रिप्ट को साफ और कुशल रखता है।तो मेरा सुझाव निम्नानुसार है:

अपने डेटाबेस में एक स्केलर TSQL फ़ंक्शन लिखें। यह SQL REPLACE फ़ंक्शन का उपयोग करता है और कुछ हद तक क्रूर बल है, लेकिन यह वास्तव में अच्छा प्रदर्शन करता है। यदि आप वास्तव में अपने वेब सर्वर कोड को सरल बनाना चाहते हैं तो यह फ़ंक्शन सीधे एक चयन कथन पर या तालिका में गणना कॉलम बनाने के लिए उपयोग किया जा सकता है। वर्तमान में यह उदाहरण केवल POINT, पॉलीगॉन और मल्टीप्लिओगन का समर्थन करता है और geoJSON प्रारूप के लिए "ज्यामिति" JSON तत्व प्रदान करता है।

GetGeoJSON अदिश समारोह

CREATE FUNCTION GetGeoJSON (@geo geography) /*this is your geography shape*/ 
RETURNS varchar(max) 
WITH SCHEMABINDING /*this tells SQL SERVER that it is deterministic (helpful if you use it in a calculated column)*/ 
AS 
BEGIN 
/* Declare the return variable here*/ 
DECLARE @Result varchar(max) 

/*Build JSON "geometry" element for geoJSON*/ 

SELECT @Result = '"geometry":{' + 
    CASE @geo.STGeometryType() 
     WHEN 'POINT' THEN 
      '"type": "Point","coordinates":' + 
      REPLACE(REPLACE(REPLACE(REPLACE(@geo.ToString(),'POINT ',''),'(','['),')',']'),' ',',') 
     WHEN 'POLYGON' THEN 
      '"type": "Polygon","coordinates":' + 
      '[' + REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@geo.ToString(),'POLYGON ',''),'(','['),')',']'),'], ',']],['),', ','],['),' ',',') + ']' 
     WHEN 'MULTIPOLYGON' THEN 
      '"type": "MultiPolygon","coordinates":' + 
      '[' + REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@geo.ToString(),'MULTIPOLYGON ',''),'(','['),')',']'),'], ',']],['),', ','],['),' ',',') + ']' 
    ELSE NULL 
    END 
    +'}' 

    /* Return the result of the function*/ 
    RETURN @Result 

END 

इसके बाद, अपने GetGeoJSON समारोह अपने SELECT बयान में, उदाहरण के लिए उपयोग करें:

SELECT dbo.GetGeoJSON([COLUMN]) as Geometry From [TABLE] 

मुझे आशा है कि यह कुछ अंतर्दृष्टि प्रदान करता है और दूसरों में मदद करता है एक पद्धति की तलाश में , सौभाग्य!

+0

मुझे यह त्रुटि ज्यामिति भूगोल के साथ असंगत है – yozawiratama

+0

आपको यह त्रुटि कहां मिली? फ़ंक्शन को कॉल करते समय? यदि ऐसा है, तो यह भूगोल को तर्क के रूप में लेता है, ज्यामिति नहीं। –

3

WKT से GeoJson में कनवर्ट करने के लिए आप nettoopologySuite को nuget से उपयोग कर सकते हैं। जोड़े NetTopologySuite और NetTopologySuite.IO.GeoJSON

var wkt = "POLYGON ((10 20, 30 40, 50 60, 10 20))"; 
var wktReader = new NetTopologySuite.IO.WKTReader(); 
var geom = wktReader.Read(wkt); 
var feature = new NetTopologySuite.Features.Feature(geom, new NetTopologySuite.Features.AttributesTable()); 
var featureCollection = new NetTopologySuite.Features.FeatureCollection(); 
featureCollection.Add(feature); 
var sb = new StringBuilder(); 
var serializer = new NetTopologySuite.IO.GeoJsonSerializer(); 
serializer.Formatting = Newtonsoft.Json.Formatting.Indented; 
using (var sw = new StringWriter(sb)) 
{ 
    serializer.Serialize(sw, featureCollection); 
} 
var result = sb.ToString(); 

आउटपुट:

{ 
    "features": [ 
    { 
     "type": "Feature", 
     "geometry": { 
     "type": "Polygon", 
     "coordinates": [ 
      [ 
      [ 
       10.0, 
       20.0 
      ], 
      [ 
       30.0, 
       40.0 
      ], 
      [ 
       50.0, 
       60.0 
      ], 
      [ 
       10.0, 
       20.0 
      ] 
      ] 
     ] 
     }, 
     "properties": {} 
    } 
    ], 
    "type": "FeatureCollection" 
} 
1

विधि जेम्स के जवाब में बताया गया है महान काम करता है। लेकिन मैं हाल ही में एक त्रुटि जब वाली WKT- परिवर्तित जहां देशांतर 99

पर एक मूल्य था मैं नियमित अभिव्यक्ति बदल पाया:

@"(-?\d{1,2}\.\dE-\d+|-?\d{1,3}\.?\d*)\s(-?\d{1,2}\.\dE-\d+|-?\d{1,2}\.?\d*)\s?0?\s?0?,?" 

सूचना दूसरा "2" करने के लिए एक "3" के लिए बदल दिया गया है देशांतर तक 180 तक जाने की अनुमति दें।