- notice 스킨변경~
[Javascript] jQuery의 getJSON사용 시 다른 도메인 데이터가져오기(CrossDomain)
Posted in 자바스크립트(Javascript) // Posted at 2009/09/28 22:37예로 다음 오픈api같은 경우 callback파라메터에 메소드명을 넣어주면 "메소드명({jsondata})" 형태로 넘어옵니다.
그래서 크로스도메인을 사용하려면 이와 같이 구현해야합니다.
다음OpenAPI를 보면 위와 같이 json이 출력이 됩니다.
url : http://apis.daum.net/contents/movie?apikey=키값&q=awake&output=json&callback=aa
결과 : aa({json~~})
그래서 실제 크로스도메인형태로 구현할 때 callback함수를 받은 값을 앞에다가 그냥 넣어주면 됩니다-_-
php코드는 대충 이런식으로-_-
$json = $_GET["c"] . "(" . json데이터 . ")";
echo $json;아.......아마 저런 형태로 안하면 callback함수가 호출 되지 않고 firebug에서 이런 에러를 뿜을 꺼에요.
"invalid label"
이것 때문에 미치는 줄 알았는데, crossdomain인 경우에는 이런식으로 해줘야하더군요.
참고사이트
http://www.ajaxlines.com/ajax/stuff/article/jquery_ajax_cross_domains_using_jsonp_getjson.php
HttpRequest를 이용해서 xml을 요청한 다음에 PullParser를 이용해 한줄한줄 파싱해서 데이터로 가져오는 방식을 사용합니다.
음...JavaFX가 1.2로 업데이트 되었는데요. 기존에 HttpRequest에서 요청할 때 enqueue()라는 함수로 실행을 했는데, start()로 함수명이 바뀌었네요. start()가 깔끔하군요.
간단하게 네이버OpenAPI를 파싱해보겠습니다.
실시간 급상승 검색어를 간단히 뿌려주는 소스입니다.

main.fx
package xmlparser;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
var rankingInfo:RankingInfo = RankingInfo{
onDone: function() {
var content:String = "";
for (item in rankingInfo.ranking) {
content += "{item}\n";
}
text.content = content;
}
};
var text:Text = Text {
font: Font {
size: 16
}
x: 10
y: 30
}
Stage {
title: "Application title"
width: 250
height: 300
scene: Scene {
content: text
}
}RankingInfo.fx
package xmlparser;
import javafx.data.pull.PullParser;
import javafx.io.http.HttpRequest;
import java.lang.Exception;
public class RankingInfo {
var url:String = "http://openapi.naver.com/search?key=네이버OpenAPI키&target=rank&query=nexearch";
var p:PullParser;
var h:HttpRequest;
public var ranking:String[];
public var onDone:function() = null;
init {
ranking = [];
h = HttpRequest {
location: url
onException: function(exception:Exception) {
exception.printStackTrace();
}
onInput: function(input) {
var i;
p = PullParser {
documentType: PullParser.XML
input: input
onEvent: function(event) {
if (event.type == PullParser.START_DOCUMENT) {
ranking = [];
i = 0;
}
else if (event.type == PullParser.END_ELEMENT
and event.level == 3) {
if (event.qname.name == "K") {
println("{event.text}");
ranking[i] = event.text;
i++;
}
}
else if (event.type == PullParser.END_DOCUMENT) {
onDone();
}
}
}
p.parse();
p.input.close();
}
}
h.start();
}
}
PullParser와 HttpRequest를 이용합니다. HttpRequest를 이용해서 url을 지정해서 가져오면 onInput이 발생합니다. 여기에서 input을 PullParser에 지정을 해주면 한줄씩 읽을 때마다 onEvent가 발생하게 됩니다.
onEvent에서는 한줄씩 읽으면서 Parsing을 해주면 됩니다.
해당 엘리먼트를 가져오기위해선 문서의 레벨과 태그의 이름으로 알 수 있습니다.
<result>
<item>
<R1>
<K>투시안경</K>
<S>+</S>
<V>105</V>
</R1>
</item>
</result>위와 같은 xml이라면 <K>값을 가져오기 위해서는 K의 레벨과 K를 알면 됩니다. K레벨은 result를 0, item을 1, R1을 2, K는 3이 됩니다.
if (event.type == PullParser.END_ELEMENT and event.level == 3) {
if (event.qname.name == "K") {
println("{event.text}");
}3이고, qname.name이 K인걸 찾으면 돼요. END_ELEMENT에서 해야하는 이유는 START_ELEMENT에서하면 값이 아직 파싱이 안된 상태여서 그렇습니다-_-
JSON인 경우도 비슷해요.
단지 Pullparser.START_ELEMENT나 END_ELEMENT가 아닌, END_VALUE로 파악을 하면 됩니다.
documentType: PullParser.JSON으로 바꿔주셔야 해요.
자바스크립트에서는 외부사이트에 있는 XML파일을 불러올 수 없습니다.
그래서 저 XML을 JSON으로 바꿔줘야합니다.
XML을 JSON으로 바꿔주는 것은 야후파이프로 합니다.
야후파이프란? 외부에 있는 데이터들을 모아서 자기만의 아웃풋을 만들 수 있는 사이트!
예를 들어, A사이트의 RSS와 B사이트의 RSS를 모아서 이쁘게 정렬해서 1개의 RSS로 만들고 싶다! 라면, 야후파이프로 가능합니다. 야후파이프로 이쁘게 그려주기만 하면 되죠. 두개의 RSS사이트를 가져다 놓고, OUTPUT으로 그냥 선만 그어주면 됩니다.
또 다른 기능은 해당 데이터를 JSON으로 출력해주도록 할 수 있습니다. 파이프로 만든 주소에 파라메터값 _render를 json으로만 바꿔주면 json을 리턴하는 주소를 만들 수 있습니다. json으로 리턴하는 주소가 있다는 얘기는 javascript에서 불러와서 사용할 수 있다는 얘기죠.
야후파이프는 나중에 포스팅을....-_-;
야후파이프 주소 : http://pipes.yahoo.com/pipes/
javascript framework은 prototype으로....(이것밖에 할 줄 모름 ㅠ)
var GoogleWeatherWidget = Class.create();
GoogleWeatherWidget.prototype = {
initialize: function(contentDiv) {
$(contentDiv).addClassName('content-div');
var locationDiv = new Element('div', {id: 'location'});
var tempcDiv = new Element('div', {id: 'tempc'});
var conditionDiv = new Element('div', {id: 'condition'});
var windDiv = new Element('div', {id: 'wind'});
var iconDiv = new Element('div').insert(new Element('img', {id: 'icon'}));
$(contentDiv).insert(locationDiv); $(contentDiv).insert(tempcDiv);
$(contentDiv).insert(conditionDiv); $(contentDiv).insert(windDiv);
$(contentDiv).insert(iconDiv);
this.pollingListener = this.pollingProc.bindAsEventListener(this);
new PeriodicalExecuter(this.pollingListener, 60);
this.pollingProc();
},
pollingProc: function() {
var url = 'http://pipes.yahoo.com/pipes/pipe.run?'
url += '&_id=eBxyJgZh3RGQLC8B6icw5g';
url += '&_render=json';
url += '&location=incheon';
url += '&_callback=parseResponse';
// 이놈을 추가하면 캐쉬에서 안불러오고 계속해서 불러오는군요 ^^
url += '&' + Math.round(Math.random()* (new Date().getTime()));
if ($('weatherInfo')) {
$('weatherInfo').remove();
}
var weatherInfo = new Element('script',{
id: 'weatherInfo',
type: 'text/javascript',
src: url});
$$('head')[0].insert(weatherInfo);
}
}
function parseResponse(data) {
$('location').update(data.value.items[0].location);
$('tempc').update(data.value.items[0].tempc + '℃');
$('icon').src = 'http://www.google.co.kr/ig/' + data.value.items[0].icon;
$('condition').update(data.value.items[0].condition);
$('wind').update(data.value.items[0].wind);
}
소스를 분석해보면, new PeriodicalExecuter(this.pollingListener, 60);부분에서 60초마다 this.pollingProc을 수행하겠다는 얘기입니다. 핵심은 pollingProc입니다.
pollinProc을 보면,
url += '&_id=eBxyJgZh3RGQLC8B6icw5g';
url += '&_render=json';
url += '&location=incheon';
url += '&_callback=parseResponse';
location값으로 지역값을 받도록 했구요. callback함수는 parseResponse로 했습니다. url이 head에 붙으면, parseResponse가 호출이 됩니다.
parseResponse를 보면, 해당 div에 값을 업데이트 시켜주는 방식으로 되어있습니다.
결론은.....xml로 리턴하는 RSS나 다른 API정보들도 웹에서 javascript를 이용하면 불러올 수 있다? 정도?-_-;
아래는 위젯......위젯 그까이꺼......심플해야지....-_-; 초간단 날씨위젯!
절대...그냥 표시한 거 아닙니다-_-; 구글에서 긁어와서 보여주는 겁니다-_-;
-
-
머드초보
아 캐쉬문제는 여기처럼 하면 되는군요 ^^
http://utsman.tistory.com/89
url을 유니크하게 날려주면 해결이 되는군요.
캐쉬가 참 여러가지로 힘들게 하는군요.
혼자서 댓글달고....혼자서 댓글에 댓글달고...-_-;
-
-
-
-
박스농사
혹 저방법외에 다른방법은 없을까요?
다른문제이긴 하지만...
J2EE서버를 내렷다가 올리면 캐쉬내용이 사라지겟죠?
근데 왜 안사라지지 ㅠ_ㅠ
하나씩 다 내렷다가 올리는중인데..계속 살아있군요 망할xml-
머드초보
안녕하세요~
저는 저 방법밖에 모르겠네요 ㅠ
xml이 바뀌었는데, 그 전내용을 불러오는 문제인가요?
url만 다르게 불러오면 되던데...잘 모르겠네요 ㅠ
-
-
아이린
이미지가 안보여서 살펴보니, 경로가
http://www.google.co.kr/ig//ig/images/weather/mostly_cloudy.gif
처럼 되어있더군요... /ig/ 부분이 중복되어 있습니다.
아뭏든, 많은 참고가 되었습니다. -
클라이언트에서 ajax로 요청했을 때 자료를 손쉽게 파싱하기 위해서 json으로 클라이언트에 던져줄 때가 편할 때가 있습니다. 그래서 손쉽게 json으로 변환하는 라이브러리가 있습니다.
http://json-lib.sourceforge.net/
여기보면 json-lib라는 놈이 있는데 json으로 손쉽게 변환해주는 라이브러리입니다.
이것들이 필요하다더군요. 위에 4개는 apache에 가면 있구요. ezmorph는 구글링해서 찾아서 받으세요.
그리고 JSON-LIB인 json-lib-2.2.1-jdk15.jar가 필요합니다.
사용법은 매우 간단합니다.
public class JsonTest {
@Test
public void Bean2Json()
{
MyBean myBean1 = new MyBean();
myBean1.setId(1);
myBean1.setName("mudchobo");
MyBean myBean2 = new MyBean();
myBean2.setId(2);
myBean2.setName("shit");
List<MyBean> mybeanList = new ArrayList<MyBean>();
mybeanList.add(myBean1);
mybeanList.add(myBean2);
JSONArray jsonArray = JSONArray.fromObject(mybeanList);
System.out.println("mybeanList - " + jsonArray);
Map<String, Object> map = new HashMap<String, Object>();
map.put("beanlist", jsonArray);
JSONObject jsonObject = JSONObject.fromObject(map);
System.out.println("json - " + jsonObject);
}
}
Bean 2개를 List에 add를 한다음에 JSONArray라는 객체가 List를 배열로 만드는놈입니다.
mybeanList - [{"id":1,"name":"mudchobo"},{"id":2,"name":"shit"}]
이런식으로 만듭니다.
저거를 JSONObject클래스를 이용해서 앞에 이름을 붙여줍니다. Map을 이용하면 됩니다
Map을 이용해서 put에서 첫번째 인자에 이름을 넣고, 두번째 인자에 방금 생성한 Array를 넣으면 됩니다.
그리고 JSONObject.fromObject메소드를 이용해서 생성하게 되면 이렇게 됩니다.
json - {"beanlist":[{"id":1,"name":"mudchobo"},{"id":2,"name":"shit"}]}
이상입니다-_-;
-
Keep Burning
안녕하세요.
http://www.json.org/ 안에 있는 기존 lib만 사용하다가 문제점이 생겨서(List에 있는 bean은 제대로 못 만들더군요...) 고생하고 있었는데, 좋은 방법 가르쳐 주셔서 감사합니다. -

